lecture4 ::
forall (m :: *) . Monoid m
⇒ [m] → m
lecture4 =
foldr mappend mempty
Types really can help!
What can go wrong?..
But types can't help you much if you don't use their true power...
newtype Hash = MkHash String
class Hashable a where
hash :: a > Hash
hashPair :: Int > Hash
hashPair n = hash (n, n)
hashPair :: Int > Hash
hashPair n = hash n  oops, this is valid definition!
Phantom types
newtype Hash a = MkHash String  `a` is a phantom type, not present in constructor
class Hashable a where
hash :: a > Hash a
hashPair :: Int > Hash (Int, Int)
hashPair n = hash (n, n)
hashPair :: Int > Hash (Int, Int)
hashPair n = hash n  This is no longer a valid definition!
Hash.hs:7:14: error:
• Couldn't match type ‘Int’ with ‘(Int, Int)’
Expected type: Hash (Int, Int)
Actual type: Hash Int
• In the expression: hash n
In an equation for ‘hashPair’: hashPair n = hash n
Limitations of such approach?
Some real life examples
Crypto
newtype Signature a = Signature ByteString
sign :: Binary t => SecretKey > t > Signature t
path package: welltypes paths
data Abs  absolute path
data Rel  relative path
data Dir  directory
data File  file
newtype Path b t = Path FilePath
 appending paths
(</>) :: Path b Dir > Path Rel t > Path b t
oclock package: timesafe units
data Second
data Microsecond  rough approximation
newtype Time unit = Time (Ratio Natural)
So you should understand types well enough to embrace their true power
∀ or ¬∀?
Can anybody completely explain the forall keyword in clear, plain English?
No.
Who said OOP?
showAll :: Show a => [a] > [String]
showAll = map show
ghci> showAll [2, 3]
["2", "3"]
ghci> showAll [1, "ABA"]  ??
No instance for (Num [Char]) arising from the literal ‘1’
In the expression: 1
In the first argument of ‘showAll’, namely ‘[1, "ABA"]’
In the expression: showAll [1, "ABA"]
a type variable is fixed
ghci> [False, "ABA"]  fails
Couldn't match expected type ‘Bool’ with actual type ‘[Char]’
In the expression: "ABA"
In the expression: [False, "ABA"]
In an equation for ‘it’: it = [False, "ABA"]
More types
ghci> reverse [2, 1, 3]
[3,1,2]
ghci> reverse [True, False]
[False,True]
applyTwo :: ([Int], [Bool])
applyTwo = let call f = (f [2, 1, 3], f [True, False]) in call reverse  (*)
 but we get:
(*):29:
No instance for (Num Bool) arising from the literal ‘2’
In the expression: 2
In the first argument of ‘f’, namely ‘[2, 1, 3]’
In the expression: f [2, 1, 3]
(*):15:
Couldn't match type ‘Int’ with ‘Bool’
Expected type: ([Int], [Bool])
Actual type: ([Int], [Int])
In the expression: call reverse
In the expression: let call f = (f ..., f ...) in call reverse
(*):20:
Couldn't match type ‘Bool’ with ‘Int’
Expected type: [Bool] > [Int]
Actual type: [Int] > [Int]
In the first argument of ‘call’, namely ‘reverse’
In the expression: call reverse
 and we want
gchi> applyTwo
([3,1,2], [False,True])
forall
id :: a > a
id x = x
 real type with explicit forall
id :: forall a . a > a
id x = x
Read as:
For every type a this function
can be considered to have type a → a
forall example
ghci> applyTwo id  works like magic
([2,1,3],[True,False])
ghci> applyTwo reverse
([3,1,2],[False,True])
applyTwo :: (forall a . [a] > [a]) > ([Int], [Bool])
applyTwo f = (f [2, 1, 3], f [True, False])
applyTwo :: ([a] > [a]) > ([Int], [Bool])  doesn't compile
applyTwo f = (f [2, 1, 3], f [True, False])
ghci> (\(a, b) > (reverse a, reverse b)) ("hello", [2, 1, 3])  ??
applyTwo :: forall a . ([a] > [a]) > ([Int], [Bool])  equivalent form ^
applyTwo f = (f [2, 1, 3], f [True, False])
Instead we should....
Does this work and why?
More generic applyTwo
applyTwo :: ([a] > [a]) > ([Int], [Bool])
applyTwo f = (f [2, 1, 3], f [True, False])
Trying to understand why this doesn't work
Let's make it more generic!
applyTwo :: ([a] > [a]) > [b] > [c] > ([b], [c])
applyTwo f x y = (f x, f y)
• Couldn't match type ‘b’ with ‘a’
‘b’ is a rigid type variable bound by
the type signature for:
applyTwo :: forall a b c. ([a] > [a]) > [b] > [c] > ([b], [c])
ghci> applyTwo id [2,1,3] [True,False]
([2,1,3],[True,False])
ghci> applyTwo reverse [True,False] "patak"
([False,True],"katap")
applyTwo :: (forall a . [a] > [a]) > [b] > [c] > ([b], [c])
applyTwo f x y = (f x, f y)
reverse :: forall a . [a] > [a]
applyTwo :: forall b c . (forall a . [a] > [a]) > [b] > [c] > ([b], [c])
applyTwo f x y = (f x, f y)
Type of reverse matches better our last implementation
Slide 13: <undefined error>
undefined :: forall a . a  intersection of all types
undefined = ⊥
What is undefined in Haskell (true language)?
What is undefined in bad languages?
{# LANGUAGE RankNTypes #}
Rank 0: Int
Rank 1: forall a . a > Int
Rank 2: (forall a . a > Int) > Int  could be enabled by Rank2Types
Rank 3: ((forall a . a > Int) > Int) > Int
A function type has rank n + 1 when its argument has rank n.
Int > Int
Exercises:
Int > Int  rank 0
forall a . a > a
forall a . a > a  rank 1
The rank of a type describes the depth at which universal quantifiers appear in a contravariant position, i.e. to the left of a function arrow.
(forall a . a > a) > Int
(forall a . a > a) > Int  rank 2
Int > (forall a . a > a)
forall a . Int > a > a  rank 1
forall a b . a > b > a
forall a b . a > b > a  rank 1
forall a . a > (forall b . b > a)
(a > a) > (forall b . b > b) > (c > c)
forall a b . a > b > a  rank 1
(a > a) > (forall b . b > b) > (c > c)  rank 2
So you probably have such question:
Where I need forall in real life?
Show everything existed
showAll :: Show a => [a] > [String]
showAll = map show
showAll :: forall a . Show a => [a] > [String]
showAll = map show
showAll :: Show a => [forall a . a] > [String]  'a' not in scope for Show
showAll = map show
showAll :: [forall a . Show a => a] > [String]  only bottoms
showAll = map show
{# LANGUAGE ExistentialQuantification #}
data ShowBox = forall a . Show a => SB a  existental constructor
showAll :: [ShowBox] > [String]
showAll = map (\(SB a) > show a)
ghci> showAll [SB (), SB 1, SB True]  again, this magic works
["()","1","True"]
showAll :: forall a . [Show a => a] > [String]  ImpredicativeTypes (broken)
showAll = map show
You can simulate OOPstyle of programming now!
Okay, I promised real life example...
ghci> incShow "3"  why does this work at all?
"4"
ghci> incShow "3.0"
"*** Exception: Prelude.read: no parse
How about this?
We want to deserialiaze data, perform some transformations, and then serialize back. Oh, and we want single function that will work for every type automatically.
 incShow :: ???
incShow = show . (+1) . read
ghci> :t read  our simple 'deserialize' function
read :: Read a => String > a
ghci> :t show  our simple 'serialize' function
show :: Show a => a > String
incShow :: String > String
incShow = show . (+1) . read
Type variable 'a' is not visible in type! How can we specify type?...
How to solve this problem in OOP world, btw?
Prepare for long story...
What a wonderful type system
 v1.0.0: also compiles
prepend2 :: Int > [Int] > [Int]
prepend2 x xs = pair ++ xs
where pair = [x, x]
 v3.0.0: doesn't compile!
prepend2 :: a > [a] > [a]
prepend2 x xs = pair ++ xs
where pair :: [a]
pair = [x, x]
 v0.0.0: this compiles
prepend2 :: Int > [Int] > [Int]
prepend2 x xs = pairFun x ++ xs
where pairFun y = [y, y]
 v2.0.0: compiles or not?
prepend2 :: a > [a] > [a]
prepend2 x xs = pair ++ xs
where pair = [x, x]
 v2.1.0: everything works!
prepend2 :: a > [a] > [a]
prepend2 x xs = pairFun x ++ xs
where pairFun :: a > [a]
pairFun y = [y, y]
Closer look at compiler error
 v3.0.0: doesn't compile!
prepend2 :: a > [a] > [a]
prepend2 x xs = pair ++ xs
where pair :: [a]
pair = [x, x]
Forall.hs:18:17: error:
• Couldn't match expected type ‘a1’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the type signature for:
prepend2 :: forall a. a > [a] > [a]
at Forall.hs:15:127
‘a1’ is a rigid type variable bound by
the type signature for:
pair :: forall a1. [a1]
at Forall.hs:17:919
• In the expression: x
In the expression: [x, x]
In an equation for ‘pair’: pair = [x, x]
• Relevant bindings include
pair :: [a1] (bound at Forall.hs:18:9)
xs :: [a] (bound at Forall.hs:16:12)
x :: a (bound at Forall.hs:16:10)
prepend2 :: a > [a] > [a] (bound at Forall.hs:16:1)

18  pair = [x, x]
 ^
We need some scoping...
prepend2 :: a > [a] > [a]
prepend2 x xs = pair ++ xs
where
pair :: [a]
pair = [x, x]
id :: a > a
This definition just...
...contains implicit forall!
id :: forall . a > a
Inner forall shadows toplevel forall!
prepend2 :: forall a . a > [a] > [a]
prepend2 x xs = pair ++ xs
where
pair :: forall a . [a]
pair = [x, x]
Same for functions inside where block!
 it's basically the same reason why this doesn't compile
prepend2 :: forall a b . b > [a] > [a]
prepend2 x xs = [x, x] ++ xs
XScopedTypeVariables
{# LANGUAGE ScopedTypeVariables #}
prepend2 :: forall a . a > [a] > [a]
prepend2 x xs = pair ++ xs
where
pair :: [a]  uses same type variable 'a'
pair = [x, x]
XScopedTypeVariables language extension allows to use type variables from toplevel function signature inside this function body (including where block). Works only with forall keyword!
XTypeApplications
ghci> read "3" :: Int
3
ghci> read "3.0" :: Double
3.0
 in some artifical syntax...
read :: (a :: Type) > (_ :: String) > (x :: a)
How many arguments read has?
read :: forall a . Read a => String > a
ghci> :t read
read :: Read a => String > a
ghci> read @Int "3"
3
ghci> read @Double "3.0"
3.0
ghci> :t read @Int
read @Int :: String > Int
ghci> read "3" :: Int  so, here we basically just pass Int type
3
ghci> read "3.0" :: Double
3.0
XTypeApplications: visible type application
Now we can pass types as arguments to functions!
XAllowAmbiguousTypes
 do you see problems with this code?
class Size a where
size :: Int
• Could not deduce (Size a)
from the context: Size a
bound by the type signature for:
size :: forall a. Size a => Int
{# LANGUAGE AllowAmbiguousTypes #}
class Size a where size :: Int
instance Size Int where size = 8
instance Size Double where size = 16
ghci> size  this all looks great, but how can I call 'size' function??????
• Ambiguous type variable ‘a0’ arising from a use of ‘size’
prevents the constraint ‘(Size a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance [safe] Size Double  Defined at Forall.hs:12:10
instance [safe] Size Int  Defined at Forall.hs:9:10
ghci> size @Double  use XTypeApplications
16
 simple plain haskell
class Size a where
size :: a > Int
Show must go on
 v0.0.0: this doesn't work obviously
incShow :: String > String
incShow = show . (+1) . read
Result
ghci> incShow @Int "3"
"4"
ghci> incShow @Double "3.2"
"4.2"
ghci> incShow @Rational "3 % 5"
"8 % 5"
 v0.0.1: why this doesn't work?
incShow :: (Read a, Show a, Num a) => String > String
incShow = show . (+1) . read
{# LANGUAGE AllowAmbiguousTypes #}
 v0.0.2: why still doesn't work??
incShow :: (Read a, Show a, Num a) => String > String
incShow = show . (+1) . read
{# LANGUAGE AllowAmbiguousTypes #}
{# LANGUAGE TypeApplications #}
 v0.0.3: why still this doesn't work???
incShow :: (Read a, Show a, Num a) => String > String
incShow = show . (+1) . read @a
{# LANGUAGE AllowAmbiguousTypes #}
{# LANGUAGE ScopedTypeVariables #}
{# LANGUAGE TypeApplications #}
 v1.0.0: this works!
incShow :: forall a . (Read a, Show a, Num a) => String > String
incShow = show . (+1) . read @a
New best friends
{# LANGUAGE Rank2Types #}
{# LANGUAGE RankNTypes #}
{# LANGUAGE ExplicitForAll #}
{# LANGUAGE ExistentialQuantification #}
{# LANGUAGE ScopedTypeVariables #}
{# LANGUAGE TypeApplications #}
{# LANGUAGE AllowAmbiguosTypes #}
Kinds
Types of types
ghci> :kind Int
Int :: *
ghci> :kind Char
Char :: *
ghci> :kind Maybe
Maybe :: * > *
ghci> :kind Maybe String
Maybe :: *
ghci> :kind (Maybe Maybe)  ??
data MapTree k v
= Leaf
 Node k v (MapTree k v) (MapTree k v)
MapTree :: * > * > *
MapTree a :: * > *
MapTree String v :: *
In FP everything is a function. So you think of types as of functions. And types also can be partially applied.
List type
ghci> :info []
data [] a = []  a : [a]  Defined in ‘GHC.Types’
...
ghci> :kind []
[] :: * > *  kind of list
ghci> :kind [] Int
[] Int :: *  `[] a` is the same as [a]
ghci> :kind [String]
[String] :: *
Arrow type
ghci> :info (>)
data (>) t1 t2  Defined in ‘GHC.Prim’
infixr 0 `(>)`
...
ghci> :k (>)
(>) :: * > * > *  kind of function
ghci> :k (>) Int
(>) Int :: * > *
 ((>) Int) is the same as (Int > )
Why care about kinds?
ghci> data Computable a f = Computation (f a) a
ghci> :kind Computable
Computable :: * > (* > *) > *
Your types can be parametrized by higherkinded types!
ghci> :kind Computable String
Computable String :: (* > *) > *
ghci> :kind Computable Int Maybe
Computable Int Maybe :: *
ghci> :kind Computable (Maybe String) ((>) Int)
Computable (Maybe String) ((>) Int) :: *
⇒ new level of abstraction
newtype IntComputation f = MkIntComp (f Int)  option 1: new data type
type IntComputation f = Computable Int f  option 2: specialization
ghci> :k IntComputation  in both cases
IntComputation :: (* > *) > *
Not convinced?
You must understand compiler errors
Kind polymorphism
ghci> :set XKindSignatures
ghci> :set XPolyKinds
ghci> data PolyComputable (f :: k > *) (a :: k) = PolyComputation (f a)
ghci> :kind PolyComputable
PolyComputable :: (k > *) > k > *
Parametric kinds (remeber: types are functions)
ghci> :k PolyComputable Maybe
PolyComputable Maybe :: * > *
ghci> :k PolyComputable IntComputation
PolyComputable IntComputation :: (* > *) > *
Still don't see how many levels of abstractions you can have and how awesome and parametric code you can write? Well...
Higherkinded classes
class Box b where  b :: * > *
box :: a > b a
unbox :: b a > a
Not possible without types of higher kind (but possible in Haskell)
instance Box Maybe where  "instance Box (Maybe a) where" is compilation error
box = Just  ηreduce from: box a = Just a
unbox (Just a) = a
unbox Nothing = error "Can't unbox from empty context"
instance Box [] where
box :: a > [a]
box x = [x]
unbox :: [a] > a
unbox [x] = x
boxCall :: Box m => (a > b) > m a > m b
boxCall f b = box $ f $ unbox b
ghci> boxCall (+1) (Just 4)
Just 5
What kind of Haskell is it???
class Num a where ...
ghci> :kind Num
??
Hmmm, what if...
ghci> :kind Num
Num :: * > Constraint
{# LANGUAGE ConstraintKinds #}
type MyConstraints a = (Read a, Num a, Show a)
foo :: MyConstraints a => String > a > a
You can create aliases for constraints!
ghci> :set XRankNTypes
ghci> type ConstraintEndomorphism p a = p a => a > a
ghci> :kind ConstraintEndomorphism
ConstraintEndomorphism :: (* > Constraint) > * > *
And much more
Constraint aliases in real life
Expands to something like this...
Big alias
Math through types
OOP vs. Math
 not in Haskell standard libraries
class Magma m where
meld :: m > m > m
In OOP you invent programming patterns.
In FP you discover programming patterns.
1. (++)
2. max/min
3. x ○ y = xy + x^2  y
 actually in 'base'
class Semigroup m where
(<>) :: m > m > m
Associativity law for Semigroup:
1. (x <> y) <> z ≡ x <> (y <> z)
1. (++)
2. max/min
Semigroups
Monoids
 also in 'base' but...
class Semigroup m => Monoid m where
mempty :: m
Identity laws for Monoid:
2. x <> mempty ≡ x
3. mempty <> x ≡ x
1. (++)
Semigroup list instance
class Semigroup a where
(<>) :: a > a > a
sconcat :: NonEmpty a > a
stimes :: Integral b => b > a > a
instance Semigroup [a] where
(<>) = (++)
ghci> [1..5] <> [2,4..10]
[1,2,3,4,5,2,4,6,8,10]
>>> 3 * list(range(1,6))
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
Python3
ghci> concat (replicate 3 [1..5])
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
Haskell
No!
ghci> 3 `stimes` [1..5]
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
Semigroup numeric instances
instance Semigroup Int where
 Which one to choose?
1. (<>) = (+)
2. (<>) = (*)
We can combine numbers as well. But how?
newtype Sum a = Sum { getSum :: a }
newtype Product a = Product { getProduct :: a }
instance Num a => Semigroup (Sum a) where
Sum x <> Sum y = Sum (x + y)
instance Num a => Semigroup (Product a) where
Product x <> Product y = Product (x * y)
Haskell way:
emulate multiple instances for one type with multiple newtypes
ghci> 3 <> 5 :: Sum Int
Sum { getSum = 8 }
ghci> 3 <> 5 :: Product Int
Product { getProduct = 15 }
More Semigroup instances
newtype Max a = Max { getMax :: a }  max
newtype Min a = Min { getMin :: a }  min
newtype Any = Any { getAny :: Bool }  
newtype All = All { getAll :: Bool }  &&
newtype First a = First { getFirst :: a }  fst
newtype Last a = Last { getLast :: a }  snd
Use same approach for different situations
ghci> Max 3 <> Max 10 <> Max 2
Max { getMax = 10 }
ghci> Min 3 <> Min 10 <> Min 2
Min { getMin = 2 }
ghci> Any True <> Any False <> Any True
Any { getAny = True }
ghci> All True <> All False <> All True
All { getAll = False }
ghci> First 5 <> First 10 <> First 1
First { getFirst = 5 }
ghci> Last 5 <> Last 10 <> Last 1
Last { getLast = 1 }
One <> to rule them all
Welcome Monoid
 not a descendant of Semigroup for now
class Monoid a where
mempty :: a
mappend :: a > a > a
mconcat :: [a] > a
instance Monoid [a] where
mempty = []
l1 `mappend` l2 = l1 ++ l2
And all the rest is almost same...
instance (Monoid a, Monoid b) => Monoid (a,b) where
mempty = ( mempty, mempty)
(a1,b1) `mappend` (a2,b2) = (a1 `mappend` a2, b1 `mappend` b2)
Not exactly monoid...
newtype First a = First { getFirst :: a }
newtype Last a = Last { getLast :: a }
What about First and Last? How to write mempty ?
instance Semigroup a => Monoid (Maybe a) where
mempty = Nothing
Nothing `mappend` m = m
m `mappend` Nothing = m
Just m1 `mappend` Just m2 = Just (m1 <> m2)
With Maybe any Semigroup can be a Monoid
Last and First from Data.Monoid module:
newtype First a = First { getFirst :: Maybe a }
newtype Last a = Last { getLast :: Maybe a }
Function is a Monoid
instance Monoid b => Monoid (a > b) where
mempty _ = mempty
mappend f g x = f x `mappend` g x
I told you, everything is Monoid
ghci> (replicate 3 <> replicate 2) 1
[1, 1, 1, 1, 1]
And what does it mean?
Interesting Ordering of slides...
data Ordering = LT  EQ  GT
instance Monoid Ordering where
mempty = EQ
LT `mappend` _ = LT
EQ `mappend` y = y
GT `mappend` _ = GT
module Data.Ord (comparing, ...) where
comparing :: Ord a => (b > a) > b > b > Ordering
comparing p x y = compare (p x) (p y)
Why we need such instance?
data ErrorPosition = ErrorPosition
{ path :: String
, line :: Int
, offset :: Int
} deriving (Eq)
 this implementation uses Monoid instances of (>) and Ordering
instance Ord ErrorPosition where
compare = comparing path <> comparing line <> comparing offset
Lexicographically sort data types
Monoids in real life
Composability is what FP for
Vertical scaling vs. Horizontal scaling
1. Combination of plugins is a plugin
2. Combination of configurations is configuration of the same type
3. Combination of event sources is an event source
4. Combination of clusters is a cluster
5. Combination of parsers is a parser
6. Combination of streams is a stream
7. Combination of functions is a function
and so on...
data Options = Options
{ oRetryCount :: Int
, oHost :: String
, oCharacterCode :: Maybe Char
} deriving (Show, Eq)
Goal: we want to have options. We want to create multiple versions of records and combine them (defaults + CLI + file config)
Use monoid! (full details in blog post)
data PartialOptions = PartialOptions
{ poRetryCount :: Last Int
, poHost :: Last String
, poCharacterCode :: Last (Maybe Char)
} deriving (Show, Eq)
instance Monoid PartialOptions where
mempty = PartialOptions mempty mempty mempty
mappend x y = PartialOptions
{ poRetryCount = poRetryCount x <> poRetryCount y
, poHost = poHost x <> poHost y
, poCharacterCode = poCharacterCode x <> poCharacterCode y
}
And so on...
Holey Monoid
newtype HoleyMonoid m r a = HoleyMonoid { runHM :: (m > r) > a }
Monoid instance for the following data type:
ghci> format ("Person's name is " % text % ", age is " % hex) "Dave" 58
"Person's name is Dave, age is 3a"
Allows to write formatting like this ( formatting library)
Beyond Monoid to the stars
Fold
foldr and foldl
foldr :: (a > b > b) > b > [a] > b
foldl :: (b > a > b) > b > [a] > b
Simple generalization of recursion
foldr :: Foldable t => (a > b > b) > b > t a > b
foldl :: Foldable t => (b > a > b) > b > t a > b
Generalization of generalization
ghci> foldr (+) 0 [2, 1, 10]
13
ghci> foldr (*) 3 [2, 1, 10]
60
foldr (\s rest > rest + length s) 0 ["aaa", "bbb", "s"]
foldr (\rest s > rest + length s) 0 ["aaa", "bbb", "s"]
Which one correct?
Foldable type class
  Simplified version of Foldable
class Foldable t where
{# MINIMAL foldMap  foldr #}
fold :: Monoid m => t m > m
foldMap :: Monoid m => (a > m) > t a > m
foldr :: (a > b > b) > b > t a > b
Some basic instances
instance Foldable [] where
foldr :: (a > b > b) > b > [a] > b
foldr _ z [] = z
foldr f z (x:xs) = x `f` foldr f z xs
instance Foldable Maybe where
foldr :: (a > b > b) > b > Maybe a > b
foldr _ z Nothing = z
foldr f z (Just x) = f x z
Reasons to drop Haskell
ghci> length (4, [1,2,3])
???
ghci> foldr (+) 1 (Just 3)
4
ghci> foldr (+) 0 Nothing
0
ghci> length (4, [1,2,3])
1
Grocking foldr
foldr (+) 0 (1:2:3:[]) ≡ 1+2+3+0
Think of folds as replacing constructors, i.e. ':', '[]', with functions/values.
ghci> import Debug.SimpleReflect
ghci> sum [1..5] :: Expr
0 + 1 + 2 + 3 + 4 + 5
ghci> foldr f x [a,b,c]
f a ( f b ( f c x ) )
Monoidal parsing
ghci> balanced "(())"
True
ghci> balanced "(())("
False
ghci> balanced ")(())("
False
We want verify that sequance round brackets is balanced
data B = B Int Int
instance Monoid B where
mempty = B 0 0
mappend (B a b) (B c d)
 b <= c = B (a + c  b) d
 otherwise = B a (d + b  c)
parse :: Char > B
parse '(' = B 0 1
parse ')' = B 1 0
parse _ = B 0 0
balanced :: String > Bool
balanced xs = foldMap parse xs == mempty
Exercises & challenges
secondMax :: Ord a => [a] > Maybe a
ghci> secondMax [2, 1, 3]
Just 2
mconcat :: Monoid m => [m] > m
foldMap :: (Foldable f, Monoid m) => (a > m) > f a > m
foldr :: Foldable f => (a > b > b) > b > f a > b
1. Default implementation of mconcat
2. foldMap using foldr
4* foldr using foldMap
5* second maximum in list using foldr
fold :: (Foldable f, Monoid m) => f m > m
3. Default implementation of fold
Literature for all lazy people
Haskell Lecture 04: Kinda monoidal types
By Dmitrii Kovanikov
Haskell Lecture 04: Kinda monoidal types
Lecture about forall keyword, RankNTypes, kinds several standard type classes: Semigroup, Monoid, Foldable.
 780