您能否为 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 扩展并警告潜在问题;我发现这很有用,但我想我会坚持使用 Sum
、Product
以及 coerce
所做的一切。
我将此解释为询问一般前提,而不是具体询问 Monoid
和 Num
。
通过启用语言扩展 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]
所以,我认为简短的回答是:不。
假设我想使所有数字成为 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
所做的一切。
我将此解释为询问一般前提,而不是具体询问 Monoid
和 Num
。
通过启用语言扩展 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]
所以,我认为简短的回答是:不。