作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在为表达式定义一个 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)
,所以我可以在a2上
,但是如果我想在fmap
a1
或r
上fmap
,我发现不可能使用DeriveFunctor
与 newtype
,因为以下代码不起作用:
newtype ExprR a1 a2 r = MkExprR { getExpr :: Expr r a1 a2 }
deriving instance Functor (ExprR a1 a2)
如果我只需要两个类型参数,那么 Bifunctor 可能是个好主意,并且确实有一些包提供了 DeriveBifunctor,但是如果我们需要三个怎么办?我们需要 DeriveTrifunctor 或 DeriveQuadfunctor 等吗?
而且,如果我们需要的不仅仅是仿函数
怎么办?考虑可折叠
、可遍历
等
这个问题有解决办法吗?人们在haskell实践中如何解决这个问题?
最佳答案
不是对你的问题的直接回答,而是一种观察。如果这是您正在使用的真实类型,则可以使用一些因式分解。 a1
和 a2
的用法相同,每个节点使用一次。您可以考虑这一点。
data ExprNode r a = ExprNode (ExprF r a) a
-- it's a bifunctor
data ExprF r a
= Ref r
| App FunName [ExprNode r a]
| Lit Value
-- it's a bifunctor
type Expr r a1 a2 = ExprNode r (a1, a2)
现在您所需要的只是双仿函数。您是否想要这样做取决于您对 a1
和 a2
的预期含义,但我怀疑您确实想这样做。分解数据类型的一致性可以显着清理代码的其余部分:它可以梳理出隐藏的泛化机会,揭示您所依赖的标准结构,并通过更多地依赖标准库来减少样板函数的数量。
关于haskell - 如何在 Haskell 中派生多个 Functor 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54176021/
我是一名优秀的程序员,十分优秀!