Я определяю 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)
Теперь использование DeriveFunctor
может помочь мне определить instance Functor (Expr r a1)
, поэтому я могу fmap
более a2
, но если я хочу fmap
более a1
или r
, я нахожу, что это невозможно использовать DeriveFunctor
с 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
и т. д.
Есть ли решение этой проблемы? как люди решают эту проблему в практике хаскелла?