回想一下,在数学中,岩浆是一个带有二元运算的集合。我在Haskell中定义了一个岩浆类型类:
class Magma a where
multiplication :: a -> a -> a
当然,任何带有连接运算符的类型的列表都构成了一个岩浆,实际上下面的工作在Haskell中:
instance Magma [a] where
multiplication x y = x ++ y
同样,带有加法的实数形成了一个岩浆,但下面的实例声明在Haskell中不起作用:
instance (Num a) => Magma a where
multiplication x y = x + y
你能解释一下为什么第一个实例声明能很好地工作,而第二个带有类型约束的声明不起作用吗? (我正在使用ghc。)
答案 0 :(得分:2)
您需要FlexibleInstances
和UndecidableInstances
语言扩展程序:
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class Magma a where
multiplication :: a -> a -> a
instance (Num a) => Magma a where
multiplication x y = x + y
或者,使用新类型:
newtype Sum a = Sum { getSum :: a }
instance (Num a) => Magma (Sum a) where
multiplication x y = Sum $ getSum x + getSum y
请参阅Edward Kmett answer why the latter is a better approach.
另请注意,您的Magma类型类与Data.Monoid
有很多共同之处,特别是您添加的Num实例 与Monoid instance for Sum
type重叠。
您还可以在乘法中为Monoid instance for Product
type中的数字类型定义实例。