【发布时间】:2013-12-18 16:10:42
【问题描述】:
我试图弄清楚 Haskell 中 deriving Functor 的确切规则是什么。
我已经看到了 message postings 和 test code 的相关信息,但我似乎无法找到有关规则是什么的官方文档。有人可以澄清和/或指出我正确的地方吗?
【问题讨论】:
-
DeriveFunctor最初是在 GHC 6.12 中引入的,但它的发行说明没有提供任何额外的线索。
我试图弄清楚 Haskell 中 deriving Functor 的确切规则是什么。
我已经看到了 message postings 和 test code 的相关信息,但我似乎无法找到有关规则是什么的官方文档。有人可以澄清和/或指出我正确的地方吗?
【问题讨论】:
DeriveFunctor 最初是在 GHC 6.12 中引入的,但它的发行说明没有提供任何额外的线索。
要使用deriving Functor,您必须启用DeriveFunctor 语言编译指示并将其应用于具有协变最终类型变量的多态类型——换句话说,该类型允许有效的Functor 实例。然后它会派生出“明显的”Functor 实例。
过去有人担心派生实例不如手动编码的高效,尽管我似乎找不到那种材料。
据我所知,算法本身是first proposed by Twan Van Laarhoven in 2007,并且大量使用了通用 Haskell 编程。
【讨论】:
不幸的是,实际执行该操作的代码有点麻烦。我相信这主要是因为更早的、更简单的代码有时会导致编译时间过长。 Twan van Laarhoven 想出了当前的代码来解决这个问题。
派生的Functor 实例总是做显而易见的事情。这通常很好,但偶尔会错过机会。例如,假设我写
data Pair a = Pair a a deriving Functor
data Digit a = One a | Two a a deriving Functor
data Queue a =
Empty
| Single a
| Deep !(Digit a) (Queue (Pair a)) !(Digit a) deriving Functor
这将生成(在 GHC 8.2 中)
instance Functor Queue where
fmap ...
x <$ Empty = Empty
x <$ Single y = Single x
x <$ Deep pr m sf = Deep (x <$ pr) (fmap (x <$) m) (x <$ sf)
最后一种情况可以手工写得更好:
x <$ Deep pr m sf = Deep (x <$ pr) (Pair x x <$ m) (x <$ sf)
您可以使用-ddump-deriv查看实际派生代码。
【讨论】: