定义以下简单树结构后
data Tree a = Leaf | Branch (Tree a) a (Tree a)
我尝试为其定义Foldable
个实例,仅定义foldMap
并使用foldrDefault
和foldlDefault
函数:
instance treeFoldableInstance :: Foldable Tree where
foldr = foldrDefault
foldl = foldlDefault
foldMap f Leaf = mempty
foldMap f (Branch left a right) = foldMap f left <> (f a) <> foldMap f right
然而,这导致:
The value of treeFoldableInstance is undefined here, so this reference is not allowed.
当我明确定义foldl
和foldr
时,它会编译。这个错误的文档告诉我有关懒惰的信息,但这在哪里适用?
答案 0 :(得分:7)
这是因为使用foldlDefault
和foldrDefault
需要您正在尝试构建的字典,并且由于严格评估PureScript,这是不可能的。
这里最简单的解决方法可能就是尝试:
instance treeFoldableInstance :: Foldable Tree where
foldr f = foldrDefault f
foldl f = foldlDefault f
foldMap f Leaf = mempty
foldMap f (Branch left a right) = foldMap f left <> (f a) <> foldMap f right
通过eta扩展foldr
和foldl
定义,它会延迟自引用,因为desugared代码会变成类似:
foldr = \f -> foldrDefault treeFoldableInstance f
因此,treeFoldableInstance
的引用仅在传入f
后进行评估,而不是在treeFoldableInstance
声明期间进行评估。