I'm defining an AST for expression, and it has three type arguments, like following:
{-# language DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
-- | a general represetation of an expression
-- , with ref info contained in r and two attributes contained in a1, a2
data Expr r a1 a2
= Ref r a1 a2
| App FunName [Expr r a1 a2] a1 a2
| Lit Value a1 a2
deriving (Functor, Foldable, Traversable)
Now using DeriveFunctor
can only help me to define instance Functor (Expr r a1)
, so I can fmap
over a2
, but if I want to fmap
over a1
or r
, I find that it is impossible to use DeriveFunctor
with a newtype
, since the following code doesn't work:
newtype ExprR a1 a2 r = MkExprR { getExpr :: Expr r a1 a2 }
deriving instance Functor (ExprR a1 a2)
If I need only two type arguments, then Bifunctor
may be a good idea, and there indeed is some package which provide DeriveBifunctor
, but what if we need three? do we need DeriveTrifunctor
or DeriveQuadfunctor
etc. ?
And, what if we need more than Functor
? considering Foldable
, Traversable
etc.
Is there any solution about this problem? how does people solve this problem in haskell practice?