树型可折叠,"value of instance is undefined here, so this reference is not allowed"

Foldable for Tree type, "value of instance is undefined here, so this reference is not allowed"

定义如下简单树结构后

data Tree a = Leaf | Branch (Tree a) a (Tree a)

我尝试为其定义一个 Foldable 实例,仅定义 foldMap 并使用 foldrDefaultfoldlDefault 函数:

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.

当我明确定义 foldlfoldr 时,它会编译。这个错误的文档告诉我懒惰,但这在这里如何应用?

出现这种情况是因为使用 foldlDefaultfoldrDefault 需要您尝试构建的字典,而且由于 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 扩展 foldrfoldl 定义,它延迟了自我引用,因为脱糖代码变成了这样的:

foldr = \f -> foldrDefault treeFoldableInstance f

所以对treeFoldableInstance的引用只在f传入之后才被求值,而不是在treeFoldableInstance.

的声明期间求值