可能循环数据结构的功能

时间:2013-10-12 17:32:37

标签: haskell data-structures

如果我有递归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这样的函数来处理循环结构? Racketdefine/fix的形式为此提供了一个特别好的功能,它允许您使hasA之类的函数按预期运行,并返回False的结构。上面的例子,几乎没有任何额外的代码。有没有办法在Haskell中做类似的事情?它有延伸吗?

编辑:我现在发现define/fix实际上是a macro created by Matt Might,它充分利用了Racket的元编程功能,而不是内置功能,但这并不能减少它的影响。 Racket的一大特色。也许这个宏可以在Haskell中重现?

1 个答案:

答案 0 :(得分:11)

在Hackage上搜索的关键词是observable sharing。这些结果中的data-reify包看起来特别相关:

  

data-reify提供了[sic]将递归结构转换为显式图的能力。许多(隐式或显式)递归数据结构可以通过类型类实例赋予此功能。这为使用Ref进行可观察共享提供了另一种选择。