我从this lecture获取代码,但下面的演示代码出错:
newtype Sum a = Sum a
deriving (Eq,Ord,Show)
getSum::Sum a -> a
getSum (Sum a) = a
instance Num a=>Monoid (Sum a)where
mempty = Sum 0
mappend = (+)
newtype Product a = Product a
deriving (Eq,Ord,Show)
getProduct ::Product a -> a
getProduct (Product a ) = a
instance Num a => Monoid (Product a ) where
mempty = Product 1
mappend = (*)
我收到以下错误消息(使用GHC 8.2.2):
Test.hs:40:13: error:
? Could not deduce (Num (Sum a)) arising from a use of ‘+’
from the context: Num a
bound by the instance declaration at Test.hs:38:10-30
? In the expression: (+)
In an equation for ‘mappend’: mappend = (+)
In the instance declaration for ‘Monoid (Sum a)’
| 40 | mappend = (+)
Test.hs:50:13: error:
? Could not deduce (Num (Product a)) arising from a use of ‘*’
from the context: Num a
bound by the instance declaration at Test.hs:48:10-37
? In the expression: (*)
In an equation for ‘mappend’: mappend = (*)
In the instance declaration for ‘Monoid (Product a)’
50 | mappend = (*)
答案 0 :(得分:3)
通过将mappend
定义为(+)
,您可以说Sum a
本身就是Num
的成员。相反,它只包含那些成员,因此(+)
应该对这些成员进行操作。
instance Num a => Monoid (Sum a) where
mempty = Sum 0
mappend (Sum x) (Sum y) = Sum $ x + y
同样适用于Product
instance Num a => Monoid (Product a) where
mempty = Product 1
mappend (Product x) (Product y) = Product $ x * y
然后你的monoid实例按预期工作。
xs = map Sum [1..5]
ys = map Product [1..5]
mconcat xs -- 15
mconcat ys -- 120
或者,您可以按照讲座的代码在您的新类型中派生Num
。
-- from the linked lecture
newtype Sum a = Sum a
deriving (Eq, Ord, Num, Show)
newtype Product a = Product a
deriving (Eq, Ord, Num, Show)