您能否为 Haskell 中的整个 class 而不是类型创建 class 的实例?

Can you make an instance of a class not for a type but for a whole class in Haskell?

假设我想使所有数字成为 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 所做的一切。

我将此解释为询问一般前提,而不是具体询问 MonoidNum

通过启用语言扩展 FlexibleInstances、UndecidableInstances 并使用重叠实例,也许您可​​以让您编写的内容发挥作用。

但您可能不想:好像 instance Num t => Monoid t where ... 是在说

"If t is an instance of Num, here's how to make t an instance of Monoid..."

不幸的是,这是不对的。它实际上说的更像是

"Here's how to make t an instance of Monoid. First, it's necessary that t be an instance of Num. Next..."

因此,如果您这样编写实例声明,则不能再编写任何其他实例声明。 (至少不是没有 OverlappingInstances,这会带来自己的问题。)

GHC 允许您在启用某些语言扩展的情况下进行定义

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}

instance Num t => Monoid t where
  mappend = (+)
  mempty = 0

这使得 2 <> 3 结果为 5

但是 这与其他 Monoid 实例重叠,因此尝试评估 "Hello" <> "World" 结果时出现错误:Overlapping instances for Monoid [Char]

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