After defining the following simple tree structure
data Tree a = Leaf | Branch (Tree a) a (Tree a)
I tried defining a Foldable instance for it, only defining foldMap and using the foldrDefault and foldlDefault functions:
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
This, however, results in:
The value of treeFoldableInstance is undefined here, so this reference is not allowed.
When I define foldl and foldr explicitly, it compiles. The documentation for this error tells me about laziness, but how does that apply here?
This occurs due to the use of foldlDefault and foldrDefault requiring the very dictionary you are trying to construct, and since PureScript is strictly evaluated, that isn't possible.
Probably the easiest fix here is to try something like:
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
By eta-expanding the foldr and foldl definitions, it delays the self reference, as the desugared code becomes something like:
foldr = \f -> foldrDefault treeFoldableInstance f
So the reference to treeFoldableInstance is only evaluated after f is passed in, rather than during the declaration of treeFoldableInstance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With