我正在尝试为某些类型生成一个类型化的球拍程序A
,需要一个Tree
,以及两个函数A
s to an 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
My code:
(: 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
打字这个问题很难回答。但一般来说,答案不是强制转换,而是拥有一个树类型of某种类型的节点。我不了解 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>
好吧,它计算出的类型有点无用,但它们是正确的。
一旦你完成了这个,它就会知道一些美好的事情tree-value
and 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
in (map (λ (child) ...) (tree-children tree))
is a (Treeof A)
尽管它知道tree
是并且它知道什么tree-children
做。所以我不得不告诉它(旧版本有缺陷并使用tree
代替child
,掩盖了这个问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)