“派生函子”是什么意思?

29

我正在试图弄清楚在Haskell中派生Functor的规则是什么。

我看过有关它的消息发布,也看过测试代码,但我似乎找不到官方文档说明规则是什么。请问有人可以澄清并/或指导我正确的地方吗?


1
DeriveFunctor 最初是在 GHC 6.12 中引入的,但它的发布说明并没有提供任何额外的线索。 - Cirdec
2个回答

16

要使用deriving Functor,您必须启用DeriveFunctor语言扩展并将其应用于具有协变终类型变量的多态类型 - 换句话说,一种允许有效Functor实例的类型。然后它将派生“显而易见”的Functor实例。

过去曾经有人担心派生的实例不如手写的实例高效,尽管我无法找到相关材料。

该算法本身是在2007年由Twan Van Laarhoven首次提出的,并且大量使用了通用Haskell编程。


1
这个消息发布是 GHC 派生 Functor 的规范吗? - user1002430
据我所知,是的。我不知道其他Haskell实现是否有这个扩展。 - J. Abrahamson
过去人们一直担心派生实例不如手工编码的效率高,但我找不到相关材料;在这里:https://dev59.com/UFQK5IYBdhLWcg3wBrel - xilpex

6

实际执行任务的代码有点复杂。我认为这主要是因为早期更简单的代码有时会导致编译时间过长。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查看实际推导出的代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接