我正在为表达式定义一个 AST,它具有三个类型参数,如下所示:
{-# 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)
现在 usingDeriveFunctor
只能帮助我定义instance Functor (Expr r a1)
,所以我可以fmap
over a2
,但是如果我想fmap
over a1
or r
,我发现无法使用DeriveFunctor
a newtype
,因为以下代码不起作用:
newtype ExprR a1 a2 r = MkExprR { getExpr :: Expr r a1 a2 }
deriving instance Functor (ExprR a1 a2)
如果我只需要两个类型参数,那么Bifunctor
可能是个好主意,并且确实有一些包提供DeriveBifunctor
,但是如果我们需要三个呢?我们需要DeriveTrifunctor
等DeriveQuadfunctor
吗?
而且,如果我们需要更多Functor
呢?考虑Foldable
等Traversable
_
这个问题有什么解决办法吗?人们如何在haskell实践中解决这个问题?