对于树类型可折叠,"此处的实例值未定义,因此不允许此引用"

Phi*_*orf 3 purescript

在定义了以下简单的树结构之后

data Tree a = Leaf | Branch (Tree a) a (Tree a)
Run Code Online (Sandbox Code Playgroud)

我尝试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
Run Code Online (Sandbox Code Playgroud)

然而,这会导致:

The value of treeFoldableInstance is undefined here, so this reference is not allowed.
Run Code Online (Sandbox Code Playgroud)

当我定义foldlfoldr明确地,它编译.这个错误的文档告诉我有关懒惰的信息,但这在哪里适用?

gb.*_*gb. 7

这是由于使用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
Run Code Online (Sandbox Code Playgroud)

通过eta扩展foldrfoldl定义,它延迟了自引用,因为desugared代码变成类似于:

foldr = \f -> foldrDefault treeFoldableInstance f
Run Code Online (Sandbox Code Playgroud)

所以引用treeFoldableInstance只是在f传入之后才进行评估,而不是在声明之前进行评估treeFoldableInstance.