从Typed Racket Guide开始,要定义联盟类型,只需使用(define-type Some-Type (U Type1 Type2))
。
要定义多态数据结构,请使用(define-type (Opt a) (U ...))
。
我想定义一个多态二叉树
(define-type (Tree a) (U (Leaf a) Node))
(struct (a) Leaf ([val : a]))
(struct Node ([left : Tree] [right : Tree]))
(define t1 (Leaf 5))
(define t2 (Leaf 8))
(define t3 (Node t1 t2))
我想知道为什么t1的类型是Leaf
而不是Tree
,以及如何使它成为Tree
?
> t1
- : (Leaf Positive-Byte)
#<Leaf>
答案 0 :(得分:4)
执行此操作时:
(define-type (Tree a) (U (Leaf a) Node))
您将Tree
定义为类型构造函数。您不应该将Tree
本身视为一种类型,仅将(Tree Some-Concrete-Type)
视为一种类型。因此将其重命名为Treeof
:
(define-type (Treeof a) (U (Leaf a) Node))
(struct (a) Leaf ([val : a]))
(struct Node ([left : Treeof] [right : Treeof]))
现在问题更清楚了。节点结构需要一个Treeof
,但是一棵树是什么?你想要的是这个:
(define-type (Treeof a) (U (Leaf a) (Node a)))
(struct (a) Leaf ([val : a]))
(struct (a) Node ([left : (Treeof a)] [right : (Treeof a)]))
现在您的示例有效:
#lang typed/racket
(define-type (Treeof a) (U (Leaf a) (Node a)))
(struct (a) Leaf ([val : a]))
(struct (a) Node ([left : (Treeof a)] [right : (Treeof a)]))
(define t1 (Leaf 5))
(define t2 (Leaf 8))
(define t3 (Node t1 t2))
答案 1 :(得分:1)
请参阅有关子类型(https://docs.racket-lang.org/ts-guide/types.html#%28part._.Subtyping%29)的参考资料。基本上,当你使用联合类型时,Racket不会破坏旧类型。例如,您可以定义类型(U String Number)
,但String
和Number
仍然可用。 1
仍会被识别为Number
,但您可以在任何需要(U String Number)
的地方使用它,因为Number
是(U String Number)
的子类型。
同样,t1
是Leaf
,因此,Racket报告t1
是Leaf
并没有错。但是,Leaf
是Tree
的子类型,因此t1
可用于需要Tree
的地方。