Tree 类型化球拍折叠树中的任意类型转换

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 (-&

我正在尝试生成一个类型化的Racket过程,对于某些类型的
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 ()))
>