Monoid is a type class. The dictionary defines Monoid as:

Singularity, semigroup with neutral element;

I think this is something from category theory, but I don’t know what this group is right now.

Let’s start with newType

The newtype keyword

The data keyword can create a type; The type keyword aliases the current type. The instance keyword makes a type an instance of a type class;

The newtype keyword creates a newtype based on an existing data type. Newtype is much like Data, but faster, but with less functionality, and can only accept value constructors, which can only take one argument.

newtype CharList = CharList { getCharList: :Char]}deriving (Eq.Show) 

ghci> CharList "this will be shown!" 
CharList {getCharList = "this will be shown!"} 
ghci> CharList "benny"= =CharList "benny" 
True 
ghci> CharList "benny"= =CharList "oisters" 
False 
Copy the code

Monoid

Let’s start with * and ++

  1. They all take two arguments
  2. The parameter and return value are of the same type
  3. There is a value that, when used as an argument, returns the same value as another argument
    1. 1 * a certain valueThe result of phi is a certain value
    2. [] ++ a listIs the result of some list
  4. When you have three or more arguments, it doesn’t matter where you put parentheses and change the order of execution, right
    1. 3 times 4 times 53 times 4 times 5.The same
    2. ([1,2] ++ [3,4]) ++ [5,6][1,2] ++ ([3,4] ++ [5,6])The same

Then look at Monoid

An instance of Monoid consists of a binary function that satisfies the associative law and an identity element.

In the definition of *, 1 is the identity element, and in the definition of ++, [] is the identity element.

class Monoid m where
    mempty :: m
    mappend :: m -> m -> m
    mconcat :: [m] -> m
    mconcat = foldr mappend mempty 
Copy the code
  • Mempty is the unit element
  • Mappend is a binary function, and the book argues that its name append is inappropriate because it does not append
  • McOncat takes a list of m and combines all of its elements into a single value via mappend
  • McOncat is implemented with Foldr by default

So most instances just need to define mempty and mappEnd. The default concat is sufficient most of the time.

The laws of monoid

mempty `mappend` x = x 
x `mappend` mempty = x 
(x `mappend` y) `mappend` z = x `mappend` (y `mappend` z) 
A 'mappend' b = b 'mappend' a, this is commutative
Copy the code

Haskell doesn’t enforce these laws, so developers have to guarantee it.

Monoid instance

  • Lists are Monoid instances
  • Is Int a Monoid instance?
    • The addition of Int satisfies Monoid’s law, and the identity element is 0
    • The multiplication of Int also satisfies Monoid’s law, and the identity element is 1
    • So how should Int become an instance of Monoid?
    • The answer is both, which is where the newtype keyword comes in

The Product and the Sum

Data.Monoid exports Product, as defined below

newtype Product a=Product{getProduct: :a}
    deriving(Eq.Ord.Read.Show.Bounded)
Copy the code

His Monoid instance is defined as follows:

instance Num a=> Monoid ( Product a) where
    mempty=Product 1
    Product x `mappend` Product y= Product (x * y)
Copy the code

Usage:

ghci> getProduct $ Product 3 `mappend` Product 9
27
ghci> getProduct $ Product 3 `mappend` mempty
3
ghci> getProduct $ Product 3 `mappend` Product 4 `mappend` Product 2
24
ghci> getProduct.mconcat.map Product$[3.4.2]
24
Copy the code

Product makes Num satisfy Monoid in the form of multiplication.

Sum is used as addition:

ghci> getSum $ Sum 2 `mappend` Sum 9
11
ghci> getSum $ mempty `mappend` Sum 3
3
ghci> getSum.mconcat.mapSum $ [1.2.3]
6
Copy the code

There are many other similar examples in the book.

But I was more focused on Monad, so I skipped it.