为什么GHC不能为Monoid派生实例?

GHC有一些语言标志,例如DeriveFunctorDeriveDataTypeable等,它们可以编译器生成除Haskell 98中允许的类型类的派生实例。这对于类似Functor东西特别Functor ,其中该类的法律规定明显的“自然”派生实例。

那么为什么不为Monoid ? 对于具有单个数据构造函数的任何数据类型来说似乎如此:

data T = MkT a b c ...

人们可以机械地产生一个Monoid实例(借口伪代码):

instance (Monoid a, Monoid b, Monoid c, ...) => Monoid T where
  mempty =
    MkT mempty mempty mempty ...
  mappend (MkT a1 b1 c1 ...) (MkT a2 b2 c2 ...) =
    MkT (mappend a1 a2) (mappend b1 b2) (mappend c1 c2) ...

我知道derive包提供了这个,但我的问题具体是GHC没有这个原因。


这是一个任意决定不能派生Monoid ,但monoids也是非常普遍的,所以通常有很多方法可以使类型变成一个monoid。 这是一个例子:

data T = A | B | C deriving (Eq, Ord, Enum)

type Mon a = (a, a -> a -> a)

m1, m2, m3, m4 :: Mon T
m1 = (A, max)
m2 = (C, min)
m3 = (A,  x y -> toEnum $ (fromEnum x + fromEnum y) `rem` 3)
m4 = (B, f4)
f4 A _ = A
f4 B x = x
f4 C _ = C

这显示了四种合理的方法使T成为monoid( Mon包含单位和二进制操作)。 第一个是幺半群取最大值,第二个幺半群取最小值,第三个幺半群取模3的算术,第四个是用于Ordering类型的幺半群。 没有什么真正突出的自然方式。


你可以问Num和其他一些类。 这将是无足轻重的:所有其他标准派生适用于具有多个构造函数的数据类型。

作为替代,您可以使用newtype T = MkT (a,b,c) deriving Monoid派生newtype T = MkT (a,b,c) deriving Monoid

类似的扩展:你可以使空数据类型成为几乎所有类型类的一个实例。

deriving条款始终是Haskell的临时和不方便的部分,因为它仅适用于预定义的类。 增加更多的临时扩展会使语言复杂化。 相反,GHC最近得到了对通用派生的支持。

链接地址: http://www.djcxy.com/p/43443.html

上一篇: Why can't GHC derive instances for Monoid?

下一篇: What's the theoretical basis for existential types?