dds/scribblings/functions.scrbl

154 lines
5.4 KiB
Racket

#lang scribble/manual
@(require scribble/example racket/sandbox
(for-label typed/racket/base "../functions.rkt" dds/utils
typed/racket/unsafe))
@title[#:tag "functions"]{dds/functions: Formal Functions}
@defmodule[dds/functions]
This modules provides some definitions for working with functions: tabulating,
(re)constructing from tables, generating random functions, etc.
Some definitions of particular kinds of functions are also provided (threshold
Boolean functions, etc.).
@(define functions-evaluator
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-memory-limit 50])
(make-evaluator 'typed/racket #:requires '((submod "functions.rkt" typed)))))
@section{Tabulating functions}
@defproc[(tabulate [func (-> a ... b)]
[doms (List (Listof a) ... a)])
(Listof (Listof (U Any b)))]{
Given a function @racket[func] and a list of domains @racket[doms] for each of
its arguments, in order, produces a list of lists giving the values of
arguments and the value of the functions for these inputs.
@examples[#:eval functions-evaluator
(tabulate (λ (x y) (and x y)) '((#f #t) (#f #t)))
]}
@defproc[(tabulate/strict [func (-> a ... b)]
[doms (List (Listof a) ... a)])
(Listof (List (List a ...) (Listof b)))]{
Like @racket[tabulate], but the types of the arguments of @racket[func]
explicitly appear in the return type.
As of 2022-03-06, I am not able to write the type of a list first containing
elements of types @racket[a ...], followed by an element of type @racket[b].
This is why this function returns a list of lists, each containing first a list
of inputs, and then the output of @racket[func].
@examples[#:eval functions-evaluator
(tabulate/strict (λ (x y) (and x y)) '((#f #t) (#f #t)))
]}
@defproc[(tabulate/untyped [funcs procedure?]
[doms (listof list?)])
(listof list?)]{
A version of @racket[tabulate] without type checking.
As of 2022-03-06, Typed Racket cannot generate contracts for polymorphic
variable-arity functions. This means that @racket[tabulate] cannot be used
directly in untyped code and should be replaced by @racket[tabulate/untyped],
which is simply an @racket[unsafe-provide] of @racket[tabulate].
@examples[#:eval functions-evaluator
(tabulate/untyped (λ (x y) (and x y)) '((#f #t) (#f #t)))
]
The contracts in the documentation entry are provided for explanatory purposes
and are not actually enforced. Some contracts on the functions
@racket[tabulate] uses internally are still checked. For example, trying to
tabulate a function of wrong arity will still raise an error.
@examples[#:eval functions-evaluator
(module tabulate/untyped-test racket/base
(require "functions.rkt")
(tabulate/untyped (λ (x y z) (and x y z)) '((#f #t) (#f #t))))
(eval:error (require 'tabulate/untyped-test))
]}
@defproc[(tabulate* [funcs (Listof (-> a ... b))]
[doms (List (Listof a) ... a)])
(Listof (Listof (U Any b)))]{
Like @racket[tabulate], but @racket[funcs] is a list of functions taking the
same arguments over the same domains.
@examples[#:eval functions-evaluator
(tabulate* (list (λ (x y) (and x y))
(λ (x y) (or x y)))
'((#f #t) (#f #t)))
]}
@defproc[(tabulate*/strict [funcs (Listof (-> a ... b))]
[doms (List (Listof a) ... a)])
(Listof (List (List a ...) (Listof b)))]{
Like @racket[tabulate*], but the types of the arguments of the functions
explicitly appear in the return type.
As of 2022-03-06, I am not able to write the type of a list first containing
elements of types @racket[a ...], followed by a list of elements of type
@racket[b]. This is why this function returns a list of lists, each containing
first a list of inputs, and then the list of outputs of @racket[funcs].
@examples[#:eval functions-evaluator
(tabulate*/strict (list (λ (x y) (and x y))
(λ (x y) (or x y)))
'((#f #t) (#f #t)))
]
The result of @racket[tabulate*] can be obtained by applying
@racket[append-lists]:
@examples[#:eval functions-evaluator
(require (only-in "utils.rkt" append-lists))
(append-lists (tabulate*/strict (list (λ (x y) (and x y))
(λ (x y) (or x y)))
'((#f #t) (#f #t))))
]}
@defproc[(tabulate*/untyped [funcs (listof procedure?)]
[doms (listof list?)])
(listof list?)]{
A version of @racket[tabulate*] without type checking.
As of 2022-03-06, Typed Racket cannot generate contracts for polymorphic
variable-arity functions. This means that @racket[tabulate*] cannot be used
directly in untyped code and should be replaced by @racket[tabulate*/untyped],
which is simply an @racket[unsafe-provide] of @racket[tabulate*].
@examples[#:eval functions-evaluator
(tabulate*/untyped (list (λ (x y) (and x y))
(λ (x y) (or x y)))
'((#f #t) (#f #t)))
]
The contracts in the documentation entry are provided for explanatory purposes
and are not actually enforced. Some contracts on the functions
@racket[tabulate*] uses internally are still checked. For example, trying to
tabulate a function of wrong arity will still raise an error.
@examples[#:eval functions-evaluator
(module tabulate*/untyped-test racket/base
(require "functions.rkt")
(tabulate*/untyped (list (λ (x y z) (and x y z)))
'((#f #t) (#f #t))))
(eval:error (require 'tabulate*/untyped-test))
]}
@section{Constructing functions}
@section{Random functions}
@section{Threshold Boolean functions}