为什么GHC不能为Monoid派生实例? [英] Why can't GHC derive instances for Monoid?
问题描述
GHC有几个语言标志,例如 DeriveFunctor
, DeriveDataTypeable
等,它们使得编译器能够生成派生除了Haskell 98中允许的类型类以外的其他类型的实例。对于像 Functor
之类的东西来说,这尤其有意义,其中该类的规则规定了明显的自然派生实例。
那为什么不为 Monoid
?对于任何具有单一数据构造函数的数据类型来说,似乎都是这样的:
$ $ $ $ $ $ $ $ $ data T = MkT abc ...
可以机械地产生一个 Monoid
实例(原因是伪代码):
instance(Monoid a,Monoid b,Monoid c,...)=> Monoid T其中
mempty =
MkT mempty mempty mempty ...
mappend(MkT a1 b1 c1 ...)(MkT a2 b2 c2 ...)=
MkT( mappend a1 a2)(mappend b1 b2)(mappend c1 c2)...
我知道派生包提供了这个,但我的问题具体是GHC没有这个原因。
确实无法派生 Monoid
是一个任意的决定,但monoids也非常通用,所以通常会有许多方式使一个类型成为一个monoid。以下是一个例子:
data T = A | B | (a,a - > a - > a)
>
m1,m2,m3,m4:C导出(Eq,Ord,Enum)
类型Mon a = :Mon T
m1 =(A,max)
m2 =(C,min)
m3 =(A,\\ xy - > Enum $(fromEnum x + fromEnum y)` 3)
m4 =(B,f4)
f4 A _ = A
f4 B x = x
f4 C _ = C
这显示了使
T 一个monoid(带 Mon
包含单位和二元运算)。第一个是幺半群取最大值,第二个幺半群取最小值,第三个幺半群取模3算术,第四个是幺半群用于Ordering
类型。没有什么真正突出的作为自然的方式。GHC has a few language flags, such as
DeriveFunctor
,DeriveDataTypeable
etc., which enable compiler generation of derived instances for type classes other than those allowed in Haskell 98. This especially makes sense for something likeFunctor
, where the laws of that class dictate an obvious, "natural" derived instance.So why not for
Monoid
? It seems like for any data type with a single data constructor:data T = MkT a b c ...
one could mechanically produce a
Monoid
instance (excuse the pseudocode):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) ...
I'm aware that the derive package provides this, but my question specifically is whether there's a reason why GHC does not.
解决方案It's really an arbitrary decision to not be able to derive
Monoid
, but monoids are also very general so there is typically many ways to make a type a monoid. Here's an example: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
This shows four reasonable ways to make
T
a monoid (withMon
containing the unit and the binary operation). The first is the monoid from taking the maximum, the second the monoid from taking the minimum, the third the monoid from modulo 3 arithmetic, and the fourth is the monoid used for theOrdering
type. Nothing really stands out as the natural way.这篇关于为什么GHC不能为Monoid派生实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!