如何解决"无法推断(Num(Sum a))因使用'+'而引起的?#34;?

时间:2018-03-27 03:32:59

标签: haskell

我从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 = (*)

1 个答案:

答案 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)