如何在Typed Racket中定义Union多态数据结构的实例?

时间:2016-01-16 12:42:25

标签: racket typed-racket

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>

2 个答案:

答案 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),但StringNumber仍然可用。 1仍会被识别为Number,但您可以在任何需要(U String Number)的地方使用它,因为Number(U String Number)的子类型。

同样,t1Leaf,因此,Racket报告t1Leaf并没有错。但是,LeafTree的子类型,因此t1可用于需要Tree的地方。