你可以在Haskell中为一个类而不是整个类创建一个类的实例吗?

时间:2015-09-24 19:10:43

标签: haskell typeclass type-constraints

假设我想让所有数字成为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扩展并警告潜在问题;我发现信息量很大,但我想我会坚持SumProduct以及coerce所做的一切。

2 个答案:

答案 0 :(得分:21)

我将此解释为询问一般性前提,而不是专门针对MonoidNum

也许你可以通过启用语言扩展FlexibleInstances,UndecidableInstances和使用重叠实例来获得你写的工作。

但你可能不想:似乎 instance Num t => Monoid t where ...正在说

"如果tNum的实例,请按以下步骤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]

所以,我认为简短的回答是:不。