如果我有一个递归ADT
data MyType = A | B | C MyType | D MyType MyType
我可以编写一个函数来确定MyType
实例是否包含A
,如下所示:
hasA :: MyType -> Bool
hasA A = True
hasA B = False
hasA (C x) = hasA x
hasA (D x y) = (hasA x) || (hasA y)
这将适用于非循环实例,但不会停止循环结构,例如
let x = C x in hasA x
相反,在本例中,它应该返回False
。在其他情况下(使用D
),它将错误地不是停止而是返回True
。
那么,问题是如何最容易地编写像hasA
这样的处理循环结构的函数?Racket在define/fix
的形式中有一个特别好的特性,它允许您让像hasA
这样的函数按照预期运行,并为上面示例中的结构返回False
,几乎不需要任何额外的代码。有没有办法在Haskell中做类似的事情?有没有延期呢?
编辑:我现在发现define/fix
实际上是a macro created by Matt Might,它利用了球拍的元编程功能,而不是一个内置的功能,但这并不会使它成为球拍的一个很好的功能。也许这个宏可以在Haskell中重现?
发布于 2013-10-13 08:44:35
在Hackage上搜索的关键字是observable sharing。这些结果中的data-reify包看起来特别相关:
data-reify
为sic提供了将递归结构转换为显式图形的能力。许多(隐式或显式)递归数据结构可以通过类型类实例赋予这种能力。这为使用Ref进行可观察的共享提供了另一种选择。
https://stackoverflow.com/questions/19337153
复制相似问题