0

I am trying to play around with monoids in Haskell, using this page: https://en.wikibooks.org/wiki/Haskell/Monoids. I entered the following information in the terminal (after importing Data.Monoid):

class Monoid a where mempty :: a mappend :: a -> a -> a mconcat :: [a] -> a mconcat = foldr mappend memptyhere newtype Sum a = Sum { getSum :: a } instance Num a => Monoid (Sum a) where mempty = Sum 0 Sum x `mappend` Sum y = Sum (x + y) 

However, when I then try Sum 5 <> Sum 6 <> Sum 10, I receive the following message:

<interactive>:115:1: error: • Non type-variable argument in the constraint: Semigroup (Sum a) (Use FlexibleContexts to permit this) • When checking the inferred type it :: forall a. (Semigroup (Sum a), Num a) => Sum a 

I don't understand what errors these are, and why Sum 5 <> Sum 6 <> Sum 10 didn't work.

2

1 Answer 1

4

The problem is that you are using your own Sum type and Monoid type class with an operator <> that is not the same function as your version of mappend. If you were to enter this program in a multi-line GHCi prompt:

> :{ Prelude| ...paste your program in here... Prelude| :} > 

and then try this instead:

> Sum 5 `mappend` Sum 6 `mappend` Sum 7 Sum 5 `mappend` Sum 6 `mappend` Sum 7 :: Num a => Sum a 

there would be no error. If you added a deriving (Show) to your Sum type, you'd even get the answer you're looking for!

Ok, modules loaded: none. λ> :{ Prelude| class Monoid a where Prelude| mempty :: a Prelude| mappend :: a -> a -> a Prelude| mconcat :: [a] -> a Prelude| mconcat = foldr mappend mempty Prelude| newtype Sum a = Sum { getSum :: a } deriving (Show) Prelude| instance Num a => Monoid (Sum a) where Prelude| mempty = Sum 0 Prelude| Sum x `mappend` Sum y = Sum (x + y) Prelude| :} λ> Sum 5 `mappend` Sum 6 `mappend` Sum 7 Sum {getSum = 18} λ> 

The rules for overriding library definitions in GHCi can be a little complicated, so it might be a better idea to put this into a xxx.hs file and load it into GHCi with :l xxx.hs for testing. If you'd tried to load this program as a xxx.hs file, you would have gotten much clearer messages about the problem:

MonoidExample2.hs:7:19-24: error: Ambiguous occurrence ‘Monoid’ It could refer to either ‘Prelude.Monoid’, imported from ‘Prelude’ at MonoidExample2.hs:1:1 (and originally defined in ‘GHC.Base’) or ‘Main.Monoid’, defined at MonoidExample2.hs:1:1 

Then, you could use the special import Prelude syntax to hide the library definitions you didn't want. The following version works as a self-contained program:

import Prelude hiding (Monoid, mempty, mappend, mconcat, (<>)) class Monoid a where mempty :: a mappend :: a -> a -> a mconcat :: [a] -> a mconcat = foldr mappend mempty newtype Sum a = Sum { getSum :: a } deriving (Show) instance Num a => Monoid (Sum a) where mempty = Sum 0 Sum x `mappend` Sum y = Sum (x + y) (<>) :: Monoid a => a -> a -> a (<>) = mappend main :: IO () main = print $ Sum 5 <> Sum 6 <> Sum 10 

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.