无法推断(半组(可选a))由实例声明的超类引起

时间:2018-09-08 17:51:27

标签: haskell

“ Haskell编程:从第一原理”中的以下代码无法编译:

module Learn where
import Data.Semigroup
import Data.Monoid

-- Exercise: Optional Monoid
data Optional a = Nada
                | Only a
                deriving (Eq, Show)

instance Monoid a => Monoid (Optional a) where
 mempty = Nada
 mappend Nada Nada = Nada
 mappend (Only a) Nada = Only $ mappend a mempty
 mappend Nada (Only a) = Only $ mappend mempty a
 mappend (Only a) (Only b) = Only $ mappend a b

它出现以下错误:

intermission.hs:11:10: error:
    • Could not deduce (Semigroup (Optional a))
        arising from the superclasses of an instance declaration
      from the context: Monoid a
        bound by the instance declaration at intermission.hs:11:10-40
    • In the instance declaration for ‘Monoid (Optional a)’
   |
11 | instance Monoid a => Monoid (Optional a) where
   |   

为了阻止ghc抱怨,我必须创建Optional a的半组实例并定义“ <>”。这对我来说不太有意义,并且想知道我是否忽略了某些事情。

2 个答案:

答案 0 :(得分:8)

NOTE: Semigroup is a superclass of Monoid since base-4.11.0.0.

其中的超类列表发展缓慢。当提出了新的有用类时,将更新旧类的API以反映它们之间的关系。不幸的是,它破坏了旧代码。 Base 4.11.1.0已于2018年4月发布,对Monoid进行了重大更改。

答案 1 :(得分:1)

这是解决方案:

import Data.Monoid

data Optional a = Nada | Only a deriving (Eq, Show)

instance Monoid a => Monoid (Optional a) where
   mempty = Nada

instance Semigroup a => Semigroup (Optional a) where
  Nada <> (Only a) = Only a
  (Only a) <> Nada = Only a
  (Only a) <> (Only a') = Only (a <> a')
  Nada <> Nada = Nada

main :: IO ()
main = do
  print $ Only (Sum 1) `mappend` Only (Sum 1)