3 Formal Functions
3.1 Motivation
Pattern matching usually goes together with algebraic types. Racket’s structures and lists could be used as constructors for algebraic data types, but they use have some drawbacks.
(struct N (x) #:transparent) (struct 1+ (x) #:transparent) (struct Sum (x y) #:transparent) (struct Prod (x y) #:transparent)
(define calculate (replace-all-repeated (N 0) --> 0 (N n) --> (1+ (N (- n 1))) (Sum x 0) --> x (Sum x (1+ y)) --> (1+ (Sum x y)) (Prod _ 0) --> 0 (Prod x (1+ y)) --> (Sum x (Prod x y))))
> (calculate (Sum (N 2) (N 3))) (Sum (N 2) (N 3))
(define calculate2 (replace-repeated (N 0) --> 0 (N n) --> (1+ (N (- n 1))) (Sum x 0) --> x (Sum x (1+ y)) --> (1+ (Sum x y)) (Prod _ 0) --> 0 (Prod x (1+ y)) --> (Sum x (Prod x y)) (1+ x) --> (1+ (calculate2 x)) (Sum x y) --> (Sum (calculate2 x) (calculate2 y)) (Prod x y) --> (Prod (calculate2 x) (calculate2 y))))
> (calculate2 (Sum (N 2) (N 3))) (1+ (1+ (1+ (1+ (1+ 0)))))
> (calculate2 (Prod (N 2) (N 3))) (1+ (1+ (1+ (1+ (1+ (1+ 0))))))
Moreover, we need explicit recursion, therefore we have lost the ability to make anonymous rewriting system. Finally, use of structures fixes the number of their fields, so it is impossible to write a pattern like (Sum x __) and to have any number of arguments, which is reasonable when dealing with sums.
(define calculate3 (replace-all-repeated `(N 0) --> 0 `(N ,n) --> `(1+ (N ,(- n 1))) `(Sum ,x 0) --> x `(Sum ,x (1+ ,y)) --> `(1+ (Sum ,x ,y)) `(Prod ,_ 0) --> 0 `(Prod ,x (1+ ,y)) --> `(Sum ,x (Prod ,x ,y))))
> (calculate3 '(Sum (N 2) (N 3))) '(1+ (1+ (1+ (1+ (1+ 0)))))
> (calculate3 '(Prod (N 2) (N 3))) '(1+ (1+ (1+ (1+ (1+ (1+ 0))))))
Looks much better, but a bit prickly because of quotes and commas. It may become even worse-looking if we use blanks _ and ___ a lot. Using explicit list constructor does not help either, it makes patterns more difficult to read and write: (list 'Sum x (list '1+ y)).
(define-formal N 1+ Sum Prod) (define calculate4 (replace-all-repeated (N 0) --> 0 (N n) --> (1+ (N (- n 1))) (Sum x 0) --> x (Sum x (1+ y)) --> (1+ (Sum x y)) (Prod _ 0) --> 0 (Prod x (1+ y)) --> (Sum x (Prod x y))))
> (calculate4 (Sum (N 2) (N 3))) '(1+ (1+ (1+ (1+ (1+ 0)))))
> (calculate4 (Prod (N 2) (N 3))) '(1+ (1+ (1+ (1+ (1+ (1+ 0))))))
Besides, formal functions could be usefull in general. For example in exploring functional programming:
> (define-formal f g h)
> (map f '(a b c)) '((f a) (f b) (f c))
> (foldl g 'x0 '(a b c)) '(g c (g b (g a x0)))
> (foldr g 'x0 '(a b c)) '(g a (g b (g c x0)))
> ((compose f g h) 'x 'y) '(f (g (h x y)))
Examples "peano.rkt" and "logics.rkt" demonstrate the use of formal functions. Rules using structures are shown in "turing.rkt".
3.2 Declaring Formal Functions
(define-formal id ...)
Examples: | |||||||||||
|
Examples: | |||||||||||
|