74 lines
1.4 KiB
Plaintext
74 lines
1.4 KiB
Plaintext
|
|
(define-data-type list
|
|
(null? null)
|
|
(pair?
|
|
(cons car cdr)
|
|
(car type car set-car!)
|
|
(cdr pair cdr set-cdr!)))
|
|
|
|
=>
|
|
|
|
(define null 0)
|
|
cons etc. as before
|
|
|
|
Type as before, except that LIST is defined to be a datatype
|
|
that includes NULL and PAIRs. NULL and PAIRs are defined to
|
|
be subtypes of LISTs. How do pairs and null get injected into
|
|
lists?
|
|
|
|
What about polymorphism? Ignore it for now.
|
|
|
|
Note that setters have a problem with destructuring - they don't work.
|
|
|
|
(if (bar? baz)
|
|
...
|
|
...)
|
|
|
|
Need temporary type bindings, a la LET. Env and type env?
|
|
Have to do shallow binding, the infer code doesn't use environments.
|
|
|
|
Hacks like
|
|
|
|
(if (bar? baz)
|
|
(error ...))
|
|
... baz is not a bar ...
|
|
|
|
won't work.
|
|
|
|
----------------
|
|
|
|
New plan. Use functions for pattern matching, with a suitable macro.
|
|
|
|
(define-data-type list delistify match-list
|
|
(null? null)
|
|
(pair?
|
|
(cons car cdr)
|
|
(car type car set-car!)
|
|
(cdr pair cdr set-cdr!)))
|
|
|
|
Defines null as 0 and pairs as before.
|
|
NULL? and PAIR? are only available at load time. There is also a
|
|
deconstructor DELISTIFY: [b list, [] -> a , [b, b list] -> a] -> a
|
|
|
|
(define (map f l)
|
|
(delistify l
|
|
(lambda ()
|
|
null)
|
|
(lambda (car cdr)
|
|
(cons (f car) (map f cdr)))))
|
|
|
|
Or, with syntax,
|
|
|
|
(define (map f l)
|
|
(match-list l
|
|
((null)
|
|
null)
|
|
((cons car cdr)
|
|
(cons (f car) (map f cdr)))))
|
|
|
|
This requires no change at all for the type checker. Hee Wack!
|
|
|
|
|
|
|
|
|