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?