如何解决在折叠树的 Typed Racket 中转换为任意类型
我正在尝试生成一个类型化的 Racket 过程,对于某些类型 A
,采用 Tree
,以及从两个 A
到 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))
)
我认为正在发生的事情是类型检查器不知道 (value tree)
也是 A
类型。有什么办法可以让我 (Cast)
成为 A
类型吗?如果没有,我将如何使其发挥作用?
解决方法
如果没有 Tree
类型的定义,就很难回答这个问题。但是一般的答案不是强制转换,而是具有一种类型,它是某种类型的 节点的树。我不了解 Racket 中的类,最不了解它们与类型化 Racket 的所有交互(这似乎都可能会发生变化),但这里是如何使用 struct
球拍:
(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>
好吧,它计算出的类型有点无用,但它们是正确的。
一旦你这样做了,它就会知道关于 tree-value
和 tree-children
的好东西:
> tree-value
- : (All (A) (-> (Treeof A) A))
#<procedure:tree-value>
> tree-children
- : (All (A) (-> (Treeof A) (Listof (Treeof A))))
#<procedure:tree-children>
这足以编写您的函数(我不确定它是否正确,但它的类型现在有意义):
(: fold-tree (All (A) (-> (Treeof A) (-> A A A) A A)))
(define (fold-tree tree f base)
(foldr f base
(cons
(tree-value tree)
;; I don't know why it needs this since it knows about tree-children
(map (λ ((child : (Treeof A)))
(fold-tree child f base))
(tree-children tree)))))
请注意,由于某种原因,即使它知道 child
是 (map (λ (child) ...) (tree-children tree))
并且它知道 {{ 1}} 确实如此。所以我不得不告诉它(旧版本有问题,使用 (Treeof A)
而不是 tree
,这隐藏了这个问题。
使用结构类型定义如 the answer 中的 tfb,
#lang typed/racket
(struct (A) tree
((value : A)
(children : (Listof (Treeof A))))
#:type-name Treeof)
以下定义有效(有点):
(: fold-tree (All (A R) (-> (Treeof A) (-> A R R) R R)))
(define (fold-tree tree f base)
(f (tree-value tree)
(foldr
(lambda ((child : (Treeof A)) (r : R))
(fold-tree child f r))
base
(tree-children tree))))
现在在交互窗口中尝试,
(fold-tree (tree 1 (list (tree 2 '()))) + 0)
工作和回报
- : Integer [more precisely: Nonnegative-Integer]
3
但尝试看似等效的
(fold-tree (tree 1 (list (tree 2 '()))) (lambda (a r) (+ a r)) 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 ()))
>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。