139 lines
4.3 KiB
Racket
139 lines
4.3 KiB
Racket
#lang typed/racket
|
|
|
|
(require typed/rackunit)
|
|
|
|
;; tagged
|
|
(begin
|
|
;; Base struct for all tagged values
|
|
(struct (B) tagged ([value : B]))
|
|
|
|
;; (define-tagged a T)
|
|
;; Use tag-a just for match and (get …)
|
|
(struct (B) tag-a tagged ()) ;; "remember" this one
|
|
;; (define-tagged #:uninterned a T)
|
|
(struct (B) tag-a-1 tag-a ()) ;; do not "rembmer" the #:uninterned ones
|
|
;; (define-tagged #:uninterned a T)
|
|
(struct (B) tag-a-2 tag-a ())
|
|
;; (define-tagged #:uninterned a T)
|
|
(struct (B) tag-a-3 tag-a ())
|
|
;; (define-tagged b T)
|
|
(struct (B) tag-b tagged ())
|
|
|
|
;; instanciation:
|
|
(tag-a "ice")
|
|
|
|
(define-syntax-rule (define-pred name? tag?)
|
|
(define-match-expander name?
|
|
(λ (stx)
|
|
(syntax-case stx ()
|
|
[(_ v)
|
|
#'(and (? tag?) (app tagged-value v))]))))
|
|
|
|
(define-pred tagged-a-1? tag-a-1?)
|
|
(define-pred tagged-a-2? tag-a-2?)
|
|
(define-pred tagged-a? tag-a?)
|
|
(define-pred tagged-b? tag-b?)
|
|
|
|
(check-true (tag-a? (tag-a "water")))
|
|
(check-true (tag-a-1? (tag-a-1 "fire")))
|
|
(check-true (tag-a-1? (tag-a-1 "air")))
|
|
(check-false (tag-a-1? (tag-a-2 "earth")))
|
|
(check-false (tag-a-1? (tag-a "salt")))
|
|
(check-false (tag-b? (tag-a "mercury")))
|
|
(check-false (tag-b? (tag-a-1 "alchemy")))
|
|
|
|
(λ ([x : (U (tag-a-1 String)
|
|
(tag-a-2 Number)
|
|
(tag-b Symbol))])
|
|
: (U Number String)
|
|
;; Match should expand to this:
|
|
(match x
|
|
[(tagged-a? v) v]
|
|
[(tagged-b? v) (symbol->string v)]))
|
|
|
|
(λ ([x : (U (tag-a-1 String)
|
|
(tag-a-2 String)
|
|
(tag-a String)
|
|
(tag-b Symbol))])
|
|
: String
|
|
;; Match should expand to this
|
|
(match x
|
|
[(tagged-a-1? v) (string-append v "-1")]
|
|
[(tagged-a-2? v) (string-append v "-2")]
|
|
[(tagged-a? v) (string-append v "-base")]
|
|
[(tagged-b? v) (symbol->string v)])))
|
|
|
|
;; struct
|
|
(begin
|
|
;; The structs seem to work well the way they are currently defined (using
|
|
;; "remember" to know all the structs with a given field).
|
|
|
|
;; (define-struct [x : Number] [y : String])
|
|
(struct (X Y) structure+x+y ([x : X] [y : Y])) ;; "remember"
|
|
(define-type structure+x=number+y=string (structure+x+y Number String))
|
|
|
|
;; (define-struct [x : Number] [y : String] [z : Symbol])
|
|
(struct (X Y Z) structure+x+y+z ([x : X] [y : Y] [z : Z])) ;; "remember"
|
|
(define-type structure+x=number+y=string+z=symbol
|
|
(structure+x+y+z Number String Symbol))
|
|
|
|
;; (define-struct [z : Symbol])
|
|
(struct (Z) structure+z ([z : Z])) ;; "remember"
|
|
(define-type structure+z=symbol (structure+z Symbol))
|
|
|
|
;; (define-struct [x : Symbol])
|
|
(struct (X) structure+x ([x : X])) ;; "remember"
|
|
(define-type structure+x=symbol (structure+x Symbol))
|
|
|
|
;; (has-get [x Number])
|
|
(define-type (has-get+x X) (U (structure+x X)
|
|
(structure+x+y X Any)
|
|
(structure+x+y+z X Any Any)))
|
|
(define-type has-get+x=number (has-get+x Number))
|
|
|
|
;; (has-get [y Number])
|
|
(define-type (has-get+y Y) (U (structure+x+y Any Y)
|
|
(structure+x+y+z Any Y Any)))
|
|
(define-type has-get+y=number (has-get+y Number))
|
|
|
|
;; (has-get [z Number])
|
|
(define-type (has-get+z Z) (U (structure+z Z)
|
|
(structure+x+y+z Any Any Z)))
|
|
(define-type has-get+z=number (has-get+z Number))
|
|
|
|
;; (get v x)
|
|
(define get-x
|
|
(λ #:∀ (X) ([s : (has-get+x X)]) : X
|
|
(cond
|
|
[(structure+x? s) (structure+x-x s)]
|
|
[(structure+x+y? s) (structure+x+y-x s)]
|
|
[(structure+x+y+z? s) (structure+x+y+z-x s)])))
|
|
|
|
;; (get v y)
|
|
(define get-y
|
|
(λ #:∀ (Y) ([s : (has-get+y Y)]) : Y
|
|
(cond
|
|
[(structure+x+y? s) (structure+x+y-y s)]
|
|
[(structure+x+y+z? s) (structure+x+y+z-y s)])))
|
|
|
|
;; (get v z)
|
|
(define get-z
|
|
(λ #:∀ (Z) ([s : (has-get+z Z)]) : Z
|
|
(cond
|
|
[(structure+z? s) (structure+z-z s)]
|
|
[(structure+x+y+z? s) (structure+x+y+z-z s)]))))
|
|
|
|
;; graph
|
|
(begin
|
|
;; define-graph
|
|
(define-type g-test (tag-a-1 (structure+x+y String g-test)))
|
|
(define-type g (tag-a-2 (structure+x+y+z String g Number)))
|
|
;; pass:
|
|
(λ ([root-node : (U g g-test)])
|
|
(ann (match root-node
|
|
[(tagged-a-1? s) (string-length (get-x s))]
|
|
[(tagged-a-2? s) (get-z s)])
|
|
Number)
|
|
(cons (get-x (tagged-value root-node))
|
|
(get-y (tagged-value root-node)))))
|