Tree 类型化球拍折叠树中的任意类型转换
我正在尝试生成一个类型化的Racket过程,对于某些类型的Tree 类型化球拍折叠树中的任意类型转换,tree,racket,fold,parametric-polymorphism,typed-racket,Tree,Racket,Fold,Parametric Polymorphism,Typed Racket,我正在尝试生成一个类型化的Racket过程,对于某些类型的a,它采用一个树,以及一个从两个as到a的函数,另一个a类型的参数,并返回一个a类型的值。我不太熟悉(All)语法,但我尝试过使用它。不幸的是,我的代码在生成时生成以下错误消息: Type Checker: Polymorphic function `foldr' could not be applied to arguments: Types: (-> a b b) b (Listof a) -> b (-&
a
,它采用一个树,以及一个从两个a
s到a
的函数,另一个a
类型的参数,并返回一个a
类型的值。我不太熟悉(All)
语法,但我尝试过使用它。不幸的是,我的代码在生成时生成以下错误消息:
Type Checker: Polymorphic function `foldr' could not be applied to arguments:
Types: (-> a b b) b (Listof a) -> b
(-> a b c c) c (Listof a) (Listof b) -> c
(-> a b c d d) d (Listof a) (Listof b) (Listof c) -> d
Arguments: (-> A A A) A (Listof Any)
Expected result: A
我的代码:
(: fold : (All (A) (Instance Tree) (A A -> A) A -> A))
(define (fold tree f base)
(foldr
f
base
(cons
(value tree)
(map
(lambda
([tree : (Instance Tree)])
(fold tree f base)
)
(children tree)
)
)
)
)
我试图简化函数,直到它开始工作,这就是它开始工作的地方:
(: fold : (All (A) (Instance Tree) (A A -> A) A -> A))
(define (fold tree f base)
(foldr f base (list base))
)
我认为发生的事情是类型检查器不知道(值树)
也是A
类型。我有没有办法把它转换成A型的?如果没有,我将如何实现这一点?如果没有树的定义,很难回答这个问题。但答案通常不是强制转换,而是有一个类型,即某种类型的节点树。我不了解Racket中的类,尤其是它们与类型化Racket的交互(似乎都会发生变化),但下面是如何使用struct
s实现这一点,类型化Racket中很好地支持这些类:
(struct (A) tree
((value : A)
(children : (Listof (Treeof A))))
#:type-name Treeof)
现在我可以检查一下:
> (tree 1 (list (tree -1 '())))
- : (Treeof (U Negative-Fixnum One))
#<tree>
> (tree 1 (list (tree 'x '())))
- : (Treeof (U 'x One))
#<tree>
这就足够编写函数了(我不确定它是否正确,但它的类型现在有意义了):
注意,由于某种原因,它无法确定(map(λ(child)…(tree children tree))
中的子项是(Treeof a)
,即使它知道树是子项,并且它知道树子项是做什么的。所以我不得不告诉它(一个较旧的版本有bug,使用了tree
而不是child
,这掩盖了这个问题。对于结构类型定义,如
#lang打字/拍子
(结构(A)树
((价值:A)
(儿童:(列表中的(Treeof A)))
#:键入名称Treeof)
以下定义(在某种程度上)有效:
(:折叠树(全部(A R)(>(A的树)(>A R)R)))
(定义(折叠树f基)
(f(树值树)
(福尔德
(lambda((child:(Treeof A))(r:r))
(折叠树子(右)
基础
(树的子树)
现在在交互窗口中尝试
(折叠树(树1(列表(树2’()))+0)
作品和回报
- : Integer [more precisely: Nonnegative-Integer]
3
但尝试看似等价的方法
(折叠树(树1(列表(树2’()))(lambda(ar)(+ar))0)
带来了很多错误
更新:由于tfb的输入,以下调用了所有工作:
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Number) (r : Number)) (+ a r)) 0)
- : Number
3
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Any) (b : Any)) (cons a b)) 0)
- : (U Zero (Pairof Any Any))
'(1 2 . 0)
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Any) (b : Any)) (cons a b)) '())
- : (U Null (Pairof Any Any))
'(1 2)
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Any) (b : (Listof Any)))
(cons a b)) '())
- : (Listof Any)
'(1 2)
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Number) (b : (Listof Number)))
(cons a b)) '())
- : (Listof Number)
'(1 2)
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda (a b) (cons a b)) '())
- : (U Null (Pairof Any Any))
'(1 2)
> (fold-tree (tree 1 (list (tree 2 '()))) cons '())
*** Type Checker: Polymorphic function `fold-tree' could not be applied to arguments:
Argument 1:
Expected: (Treeof A)
Given: (Treeof Positive-Byte)
Argument 2:
Expected: (-> A R R)
Given: (All (a b) (case-> (-> a (Listof a) (Listof a)) (-> a b (Pairof a b))))
Argument 3:
Expected: R
Given: Null
in: (fold-tree (tree 1 (list (tree 2 (quote ())))) cons (quote ()))
>
你需要在你的问题中包括“树”类型,它不是内置在类型化的框架中。更一般地说,我想知道你是否真的想使用类和对象;这可能会给这个问题带来巨大的复杂性。(请原谅我假设这是家庭作业,但是)如果问题语句需要类或提供此代码,那么当然,您会坚持使用它,但如果没有,您是否考虑过只使用structs?试试(define(fold-tree-tree-f-base)(f(tree-value-tree)(foldr(λ(child-r)(fold-tree-child-f-r))base(tree-children-tree)))
。它有效吗?我希望它的类型是(:fold tree(All(A R)(>(Treeof A)(>A R)R R))
(如果这是正确的方式写下来的话…----还有,你有一个打字错误,它应该是(fold tree child f base)
在lambda里面。@WillNess:你的版本至少键入正确,但是你需要在lambda
周围有很多明确的类型(我不知道为什么)。感谢你在我的OP的音译中找到了这个bug,这意味着我现在还需要lambda
周围的类型。要么我缺少了一些东西,要么是静态类型系统,我根本就无法继续。(还有,什么是Racket没有警告未使用的绑定?说真的,这已经是1975年了。)您可以将该类型简化为您拥有的类型。也许它不需要那么多注释。@Willenss:看起来好像(map(lambda(x)….y)
丢失了有关y
元素类型的信息,即使(我认为)它应该能够知道它。我的意思是在我的版本中。那里没有map
。)是的,你需要把它装饰成(折叠树…(lambda((x:Number)(y:Number))(+xy))0
,比如说(这是在Racket 8.0中)。看起来键入的Racket无法对(f…(lambda(x)…)中的类型进行推断,我猜是因为当它做它的事情时,它只能看到函数对象,而不能看到产生它的源(但我不知道)@tfb谢谢,我已经用更多的注释示例更新了答案。有趣的是,对于cons
,情况正好相反:不适用于裸cons
,而是适用于包装在未注释lambda中的cons
!
- : Integer [more precisely: Nonnegative-Integer]
3
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Number) (r : Number)) (+ a r)) 0)
- : Number
3
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Any) (b : Any)) (cons a b)) 0)
- : (U Zero (Pairof Any Any))
'(1 2 . 0)
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Any) (b : Any)) (cons a b)) '())
- : (U Null (Pairof Any Any))
'(1 2)
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Any) (b : (Listof Any)))
(cons a b)) '())
- : (Listof Any)
'(1 2)
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda ((a : Number) (b : (Listof Number)))
(cons a b)) '())
- : (Listof Number)
'(1 2)
> (fold-tree (tree 1 (list (tree 2 '()))) (lambda (a b) (cons a b)) '())
- : (U Null (Pairof Any Any))
'(1 2)
> (fold-tree (tree 1 (list (tree 2 '()))) cons '())
*** Type Checker: Polymorphic function `fold-tree' could not be applied to arguments:
Argument 1:
Expected: (Treeof A)
Given: (Treeof Positive-Byte)
Argument 2:
Expected: (-> A R R)
Given: (All (a b) (case-> (-> a (Listof a) (Listof a)) (-> a b (Pairof a b))))
Argument 3:
Expected: R
Given: Null
in: (fold-tree (tree 1 (list (tree 2 (quote ())))) cons (quote ()))
>