From b8f3a548220866b881d13116854a284418550217 Mon Sep 17 00:00:00 2001 From: Phil Nguyen Date: Sun, 10 Jan 2021 19:53:15 -0800 Subject: [PATCH] Provide `make-compose` macro and refactor `compose-n` implementations --- main.rkt | 109 ++++++++++++++++--------------------------------------- 1 file changed, 32 insertions(+), 77 deletions(-) diff --git a/main.rkt b/main.rkt index 48e69e6..63efeca 100644 --- a/main.rkt +++ b/main.rkt @@ -16,11 +16,17 @@ ;;; along with this program. If not, see ;;; . -#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 multi-compose multi-chain) @@ -37,82 +43,30 @@ (test-case "compose-n" (check-equal? ((compose-n add1 add1 add1) 3) 6))) -(: compose-3 (All (a b c d) - (-> (-> c d) - (-> b c) - (-> a b) - (-> a d)))) -(define (compose-3 f1 f2 f3) - (λ (x) (f1 (f2 (f3 x))))) +(define-for-syntax (make-compose-type n) + (with-syntax* ([(t ...) (generate-temporaries (make-list n 't))] + [(_ ... t₀) #'(a t ...)] + [(F ...) + (let step ([u #'a] [ts (syntax->list #'(t ...))]) + (match ts + ['() '()] + [(cons t ts*) (cons #`(#,t → #,u) (step t ts*))]))]) + #'(∀ (a t ...) (F ... → t₀ → a)))) -(: compose-4 (All (a b c d e) - (-> (-> d e) - (-> c d) - (-> b c) - (-> a b) - (-> a e)))) -(define (compose-4 f1 f2 f3 f4) - (λ (x) (f1 (f2 (f3 (f4 x)))))) +(define-syntax-parser make-compose + [(_ n:nat) + (with-syntax* ([(f ...) (generate-temporaries (make-list (syntax-e #'n) 'f))] + [T (make-compose-type (syntax-e #'n))] + [body (foldr (λ (fᵢ res) #`(#,fᵢ #,res)) #'x (syntax->list #'(f ...)))]) + #'(ann (λ (f ...) (λ (x) body)) T))]) -(: compose-5 (All (a b c d e f) - (-> (-> e f) - (-> d e) - (-> c d) - (-> b c) - (-> a b) - (-> a f)))) -(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))))))))))) +(define compose-3 (make-compose 3)) +(define compose-4 (make-compose 4)) +(define compose-5 (make-compose 5)) +(define compose-6 (make-compose 6)) +(define compose-7 (make-compose 7)) +(define compose-8 (make-compose 8)) +(define compose-9 (make-compose 9)) (module+ test (test-case "compose-3 to compose-9" @@ -152,6 +106,7 @@ #`(multi-compose #,@rev-funcs)])) (module+ test + (require racket/port) (test-case "multi-chain and multi-compose" (define f1 (λ ([x : Number]) (displayln "f1") (+ x 1))) (define f2 (λ ([x : Number]) (displayln "f2") (+ x 1)))