Provide `make-compose` macro and refactor `compose-n` implementations

This commit is contained in:
Phil Nguyen 2021-01-10 19:53:15 -08:00 committed by Sergiu Ivanov
parent bfa82e3cb2
commit b8f3a54822
1 changed files with 32 additions and 77 deletions

109
main.rkt
View File

@ -16,11 +16,17 @@
;;; along with this program. If not, see ;;; along with this program. If not, see
;;; <https://www.gnu.org/licenses/>. ;;; <https://www.gnu.org/licenses/>.
#lang typed/racket #lang typed/racket/base
(require (for-syntax syntax/parse)) (require syntax/parse/define
(for-syntax racket/base
racket/match
racket/list
racket/syntax
syntax/parse))
(provide compose-n (provide make-compose
compose-n
compose-3 compose-4 compose-5 compose-6 compose-7 compose-8 compose-9 compose-3 compose-4 compose-5 compose-6 compose-7 compose-8 compose-9
multi-compose multi-chain) multi-compose multi-chain)
@ -37,82 +43,30 @@
(test-case "compose-n" (test-case "compose-n"
(check-equal? ((compose-n add1 add1 add1) 3) 6))) (check-equal? ((compose-n add1 add1 add1) 3) 6)))
(: compose-3 (All (a b c d) (define-for-syntax (make-compose-type n)
(-> (-> c d) (with-syntax* ([(t ...) (generate-temporaries (make-list n 't))]
(-> b c) [(_ ... t₀) #'(a t ...)]
(-> a b) [(F ...)
(-> a d)))) (let step ([u #'a] [ts (syntax->list #'(t ...))])
(define (compose-3 f1 f2 f3) (match ts
(λ (x) (f1 (f2 (f3 x))))) ['() '()]
[(cons t ts*) (cons #`(#,t #,u) (step t ts*))]))])
#'( (a t ...) (F ... t₀ a))))
(: compose-4 (All (a b c d e) (define-syntax-parser make-compose
(-> (-> d e) [(_ n:nat)
(-> c d) (with-syntax* ([(f ...) (generate-temporaries (make-list (syntax-e #'n) 'f))]
(-> b c) [T (make-compose-type (syntax-e #'n))]
(-> a b) [body (foldr (λ (fᵢ res) #`(#,fᵢ #,res)) #'x (syntax->list #'(f ...)))])
(-> a e)))) #'(ann (λ (f ...) (λ (x) body)) T))])
(define (compose-4 f1 f2 f3 f4)
(λ (x) (f1 (f2 (f3 (f4 x))))))
(: compose-5 (All (a b c d e f) (define compose-3 (make-compose 3))
(-> (-> e f) (define compose-4 (make-compose 4))
(-> d e) (define compose-5 (make-compose 5))
(-> c d) (define compose-6 (make-compose 6))
(-> b c) (define compose-7 (make-compose 7))
(-> a b) (define compose-8 (make-compose 8))
(-> a f)))) (define compose-9 (make-compose 9))
(define (compose-5 f1 f2 f3 f4 f5)
(λ (x) (f1 (f2 (f3 (f4 (f5 x)))))))
(: compose-6 (All (a b c d e f g)
(-> (-> f g)
(-> e f)
(-> d e)
(-> c d)
(-> b c)
(-> a b)
(-> a g))))
(define (compose-6 f1 f2 f3 f4 f5 f6)
(λ (x) (f1 (f2 (f3 (f4 (f5 (f6 x))))))))
(: compose-7 (All (a b c d e f g h)
(-> (-> g h)
(-> f g)
(-> e f)
(-> d e)
(-> c d)
(-> b c)
(-> a b)
(-> a h))))
(define (compose-7 f1 f2 f3 f4 f5 f6 f7)
(λ (x) (f1 (f2 (f3 (f4 (f5 (f6 (f7 x)))))))))
(: compose-8 (All (a b c d e f g h i)
(-> (-> h i)
(-> g h)
(-> f g)
(-> e f)
(-> d e)
(-> c d)
(-> b c)
(-> a b)
(-> a i))))
(define (compose-8 f1 f2 f3 f4 f5 f6 f7 f8)
(λ (x) (f1 (f2 (f3 (f4 (f5 (f6 (f7 (f8 x))))))))))
(: compose-9 (All (a b c d e f g h i j)
(-> (-> i j)
(-> h i)
(-> g h)
(-> f g)
(-> e f)
(-> d e)
(-> c d)
(-> b c)
(-> a b)
(-> a j))))
(define (compose-9 f1 f2 f3 f4 f5 f6 f7 f8 f9)
(λ (x) (f1 (f2 (f3 (f4 (f5 (f6 (f7 (f8 (f9 x)))))))))))
(module+ test (module+ test
(test-case "compose-3 to compose-9" (test-case "compose-3 to compose-9"
@ -152,6 +106,7 @@
#`(multi-compose #,@rev-funcs)])) #`(multi-compose #,@rev-funcs)]))
(module+ test (module+ test
(require racket/port)
(test-case "multi-chain and multi-compose" (test-case "multi-chain and multi-compose"
(define f1 (λ ([x : Number]) (displayln "f1") (+ x 1))) (define f1 (λ ([x : Number]) (displayln "f1") (+ x 1)))
(define f2 (λ ([x : Number]) (displayln "f2") (+ x 1))) (define f2 (λ ([x : Number]) (displayln "f2") (+ x 1)))