I have a monadic function that helps translating values of type Expr to Term's. The signature is
fromDM :: (Name -> CompilerM Term) -> Expr -> CompilerM Term
I have trouble treating one case in general. I can write down implementations for every individual solution
import Control.Monad.State
type CompilerM = State Incr
newtype Incr = Incr Int deriving (Show)
generateNameM :: CompilerM Name
generateNameM = state $ \i ->
let Incr y = i
j = (+1) y
in (Name j, Incr j)
data Expr = Tuple [Expr]
data Name = Name Int
data Term = Let Name [Name] Term
fromDM :: (Name -> CompilerM Term) -> Expr -> CompilerM Term
fromDM k expr = case expr of
Tuple [e1, e2] -> do
x <- generateNameM
t' <- k x
fromDM (\z1 -> fromDM (\z2 -> pure $ Let x [z1, z2] t') e2) e1
Tuple [e1, e2, e3] -> do
x <- generateNameM
t' <- k x
fromDM (\z1 -> fromDM (\z2 -> fromDM (\z3 -> pure $ Let x [z1, z2, z3] t') e3) e2) e1
Tuple [e1, e2, e3, e4] -> do
x <- generateNameM
t' <- k x
fromDM (\z1 -> fromDM (\z2 -> fromDM (\z3 -> fromDM (\z4 -> return $ Let x [z1, z2, z3, z4] t') e4) e3) e2) e1
Now I want to substitute this with a general rule, i.e. Tuple es
. I feel this should be doable with either foldlM
or foldrM
. Yet I am kind of stuck on how to do this. So, how do I write a general rule for this transformation that works on an arbitrary list of expressions?