The following code from "Haskell Programming: From first principles" fails to compile:
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
It gives the following error:
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
|
In order to stop ghc from complaining, I had to create a semigroup instance of Optional a and define "<>". This doesn't quite make sense to me and was wondering if there was something I was overlooking.
"NOTE: Semigroup is a superclass of Monoid since base-4.11.0.0."
The list of superclasses in has been evolving slowly. As new useful classes are proposed, the API for older classes is updated to reflect their relationships. This has the unfortunate effect of breaking older code. Base 4.11.1.0 was released in April of 2018 with this breaking change to Monoid.
Here is the solution:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With