假设我想让所有数字成为Monoid
的实例。而不是像这样为每个Num
创建一个实例:
instance Monoid Int where
mappend = (+)
mempty = 0
instance Monoid Float where
mappend = (+)
mempty = 0.0
-- etc
有类似的东西吗?
instance Num t => Monoid t where
mappend = (+)
mempty = 0
有些人正在回答GHC扩展并警告潜在问题;我发现信息量很大,但我想我会坚持Sum
,Product
以及coerce
所做的一切。
答案 0 :(得分:21)
我将此解释为询问一般性前提,而不是专门针对Monoid
和Num
。
也许你可以通过启用语言扩展FlexibleInstances,UndecidableInstances和使用重叠实例来获得你写的工作。
但你可能不想:似乎 instance Num t => Monoid t where ...
正在说
"如果t
是Num
的实例,请按以下步骤t
Monoid
的实例...&#34 ;
不幸的是,这不对。它实际上说的更像是
"以下是t
Monoid.
实例的制作方法首先,t
必须是Num
的实例}。下一步..."
因此,如果您编写这样的实例声明,则无法编写任何其他实例声明。 (至少没有OverlappingInstances
,这会带来自己的问题。)
答案 1 :(得分:6)
GHC允许您使用某些语言扩展功能定义
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
instance Num t => Monoid t where
mappend = (+)
mempty = 0
这会使2 <> 3
成为5
。
但这与其他Monoid
个实例重叠,因此尝试评估"Hello" <> "World"
结果时出现错误:Overlapping instances for Monoid [Char]
所以,我认为简短的回答是:不。