From 906bd32f12c4c5ee258e63e724a584543f5238c3 Mon Sep 17 00:00:00 2001 From: Sergiu Ivanov Date: Mon, 21 Dec 2020 21:34:14 +0100 Subject: [PATCH] typed-compose.scrbl: Add the documentation. --- typed-compose.scrbl | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/typed-compose.scrbl b/typed-compose.scrbl index f70df0e..2d290bd 100644 --- a/typed-compose.scrbl +++ b/typed-compose.scrbl @@ -5,12 +5,20 @@ @title{Utilities for composing functions in Typed Racket} +@defmodule[typed-compose] + Typed Racket's @racket[compose] only takes two arguments, because in general it is difficult to specify that the return types and the argument types should be the same for two successive functions in the argument list. This package defines some further utilities to allow @racket[compose]-ing more than two functions more comfortable in Typed Racket. +@(define typed-compose-evaluator + (parameterize ([sandbox-output 'string] + [sandbox-error-output 'string] + [sandbox-memory-limit 50]) + (make-evaluator 'typed/racket/base #:requires '(typed-compose)))) + @section{License} This program is free software: you can redistribute it and/or modify it under @@ -26,3 +34,61 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see @hyperlink["https://www.gnu.org/licenses/"]{https://www.gnu.org/licenses/}. + +@section{Functions for composing functions} + +@defproc[(compose-n [proc (-> a a)] ...) (-> a a)]{ + +Compose an arbitrary number of functions of type @racket[(-> a a)]. + +@examples[#:eval typed-compose-evaluator +((compose-n add1 add1 add1) 3) +]} + +@defproc*[([(compose-3 [proc1 (-> c d)] [proc2 (-> b c)] [proc3 (-> a b)]) (-> a d)] + [(compose-4 [proc1 (-> d e)] [proc2 (-> c d)] [proc3 (-> b c)] [proc4 (-> a b)]) (-> a e)] + [(compose-5 [proc1 (-> e f)] [proc2 (-> d e)] [proc3 (-> c d)] [proc4 (-> b c)] [proc5 (-> a b)]) (-> a f)] + [(compose-6 [proc1 (-> f g)] [proc2 (-> e f)] [proc3 (-> d e)] [proc4 (-> c d)] [proc5 (-> b c)] [proc6 (-> a b)]) (-> a g)] + [(compose-7 [proc1 (-> g h)] [proc2 (-> f g)] [proc3 (-> e f)] [proc4 (-> d e)] [proc5 (-> c d)] [proc6 (-> b c)] [proc7 (-> a b)]) (-> a h)] + [(compose-8 [proc1 (-> h i)] [proc2 (-> g h)] [proc3 (-> f g)] [proc4 (-> e f)] [proc5 (-> d e)] [proc6 (-> c d)] [proc7 (-> b c)] [proc8 (-> a b)]) (-> a i)] + [(compose-9 [proc1 (-> i j)] [proc2 (-> h i)] [proc3 (-> g h)] [proc4 (-> f g)] [proc5 (-> e f)] [proc6 (-> d e)] [proc7 (-> c d)] [proc8 (-> b c)] [proc9 (-> a b)]) (-> a j)])]{ + +@racket[compose-i] composes @racket[i] functions. The rightmost function is +applied first. + +@examples[#:eval typed-compose-evaluator +(define (s->n [x : String]) (cast (string->number x) Number)) +(define fancy-add1 (compose-3 print add1 s->n)) +fancy-add1 +(fancy-add1 "1") +]} + +@defform[(multi-compose func ...) + #:contracts ([func expression])]{ + +Expands to a code applying @racket[compose] in a pairwise manner to the given +expressions. For example, @racket[(multi-compose f1 f2 f3 f4)] expands to +@racket[(compose f1 (compose f2 (compose f3 f4)))]. + +@examples[#:eval typed-compose-evaluator +((multi-compose add1 + (λ ([x : Number]) (* x 3)) + add1 + (λ ([x : Number]) (+ x 2))) + 3) +]} + +@defform[(multi-chain func ...) + #:contracts ([func expression])]{ + +Like @racket[multi-compose], but the first function in the argument list is +applied first instead of last. For example, @racket[(multi-chain f1 f2 f3 +f4)] expands to @racket[(compose f4 (compose f3 (compose f2 f1)))]. + +@examples[#:eval typed-compose-evaluator +(define f1 (λ ([x : Number]) (displayln "f1") (+ x 1))) +(define f2 (λ ([x : Number]) (displayln "f2") (+ x 1))) +(define f3 (λ ([x : Number]) (displayln "f3") (+ x 1))) +((multi-chain f1 f2 f3) 3) +((multi-compose f1 f2 f3) 3) +]}