Given an arbitrary datastructure with a fixed point, can we construct an monoidal algebra without manually specifying all cases?
Assume we are given the datatype Expr
as below. Using the recursion-schemes
library, we can derive a base functor ExprF
, which automatically also has Functor
, Foldable
and Traversable
instances.
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}
import Data.Semigroup (Sum(..))
import Data.Functor.Foldable
import Data.Functor.Foldable.TH
import Prelude hiding (fail)
data Expr = Var String
| Const Int
| Add [Expr]
| Mult [Expr]
deriving Show
$(makeBaseFunctor ''Expr)
expr :: Fix ExprF
expr = ana project $ Add [Const 1, Const 2, Mult [Const 3, Const 4], Var "hello"]
Now, let's say we want to count the number of leaves in expr
. We can easily write an algebra for such a small datastructure:
alg (ConstF _) = 1
alg (VarF _) = 1
alg (AddF xs) = sum xs
alg (MulF xs) = sum xs
Now, we can call cata alg expr
, which returns 5
, the correct result.
Let's assume Expr
grows really big and complex and we don't want to manually write cases for all data constructors. How does cata
know how to combine the results from all cases? I suspect that this is possible using Monoid
s, possibly in conjunction with the Const
functor (not entirely sure about that last part though).
fail = getSum $ foldMap (const (Sum 1) . unfix) $ unfix expr
fail
returns 4
, whereas we actually have 5
leaves. I assume that the problem lies in the fixed point, because we are only able to peel of one layer of Fix
ing and therefore the Mult [..]
is only counted as one leaf.
Is it possible to somehow generically fold the entire fixed point and collecting the results in a Monoid
-like structure without manually specifying all instances? What I want is kind of foldMap
but in a more generic way.
I have a feeling I am missing something really obvious.
fail
counts the children of the top node ofexpr
. In general, it gets nowhere near the leaves. It's not thealg
of a suitablecata
. – Toting