@@ -0,0 +1,290 @@
1+# Typeclass laws
2+
3+In the previous lecture, we introduced typeclasses as Haskell's analogue of
4+interfaces. Sometimes, good documentation of an interface explicitly describes a
5+set of invariants any implementation should uphold; in the case of Haskell, it
6+is a common rule of good manners to provide _typeclass laws_ for any typeclass
7+you define. For example, `Semigroup` and `Monoid` classes from Haskell's
8+standard library are defined like this:
9+
10+```haskell ignore
11+-- | The class of semigroups (types with an associative binary operation).
12+--
13+-- Instances should satisfy the following:
14+--
15+-- [Associativity] @x '<>' (y '<>' z) = (x '<>' y) '<>' z@
16+class Semigroup a where
17+ -- | An associative operation.
18+ --
19+ -- >>> [1,2,3] <> [4,5,6]
20+ -- [1,2,3,4,5,6]
21+ (<>) :: a -> a -> a
22+
23+-- | The class of monoids (types with an associative binary operation that
24+-- has an identity). Instances should satisfy the following:
25+--
26+-- [Right identity] @x '<>' 'mempty' = x@
27+-- [Left identity] @'mempty' '<>' x = x@
28+class Semigroup a => Monoid a where
29+ -- | Identity of '<>'
30+ --
31+ -- >>> "Hello world" <> mempty
32+ -- "Hello world"
33+ mempty :: a
34+```
35+
36+An instance of a typeclass which abides its laws is called a "lawful instance".
37+While nothing stops you from making a non-lawful instance, you should
38+nevertheless try to make your instances lawful because typeclass laws usually
39+capture an important intuition about an interaction between operations inside a
40+class: for example, we can safely omit parentheses while working with a lawful
41+semigroup instance, but with non-lawful instance we cannot.
42+
43+__Exercise 1__: define a function `foldList :: Monoid a => [a] -> a` which
44+reduces a list using methods from `Monoid` typeclass. Which laws did you
45+implicitly rely on during the implementation?
46+
47+__Exercise 2__: some types can be viewed as a monoid in more than one way, e.g.
48+both addition and multiplication on numbers. In such cases we often define
49+`newtype`s and make those instances of `Monoid`. Implement `Monoid` instances
50+for these newtypes defined below. What is needed of `Num a` instance for Monoid
51+laws to hold?
52+
53+```haskell
54+newtype Sum a = Sum { getSum :: a }
55+
56+newtype Mul a = Mul { getMul :: a }
57+```
58+
59+__Exercise 3__. Using newtypes above and the instances you've written, define
60+functions `sumList :: Num a => [a] -> a` and `productList :: Num a => [a] -> a`
61+via `foldList` defined before.
62+
63+Solutions to all exercises are given at the end of this file.
64+
65+## Endofunctor class hierarchy
66+
67+### Foldable
68+
69+Typeclasses are actually more powerful than their counterparts in other
70+languages. Most notably, we can define typeclasses which describe an interface
71+of a generic type instead of a concrete type. For example, a `Foldable` class
72+describes a type of generic collections whose contents can be folded with a
73+monoid operation:
74+
75+```haskell ignore
76+class Foldable (t :: * -> *) where
77+ foldMap :: Monoid b => (a -> b) -> t a -> b
78+```
79+
80+__Exercise 4__. Make the following tree type into `Foldable` by writing down an
81+instance for it:
82+
83+```haskell
84+data BinTree a = Leaf | Branch (BinTree a) a (BinTree a)
85+```
86+
87+### Functor
88+
89+Just like with folding, a capability of mapping over elements of a container is
90+captured in a typeclass:
91+
92+```haskell ignore
93+class Functor (f :: * -> *) where
94+ fmap :: (a -> b) -> f a -> f b
95+```
96+
97+The Functor laws capture an important property that mapping over elements should
98+not change an overall internal structure of a container. In other words,
99+
100+1. `fmap id x = x` (Identity);
101+2. `fmap g (fmap f x) = fmap (g . f) x` (Composition).
102+
103+__Exercise 5__. Write out a lawful instance of `Functor BinTree`.
104+
105+However, Functor laws are so strict that, if you can write out a lawful
106+instance, every other possible instance would behave the same. Luckily for us,
107+we can derive such an instance automatically. For example, for `BinTree` we
108+could do the following:
109+
110+```haskell ignore
111+data BinTree a = Leaf | Branch (BinTree a) a (BinTree a) deriving (Functor)
112+```
113+
114+### Applicative
115+
116+Actually, there are things more powerful than functors: applicative functors.
117+
118+```haskell ignore
119+class Functor f => Applicative f where
120+ pure :: a -> f a
121+ (<*>) :: f (a -> b) -> f a -> f b
122+ liftA2 :: (a -> b -> c) -> f a -> f b -> f c
123+```
124+
125+As notation and types are a little tricky, let us explain them bit by bit.
126+
127+* At first sight, applicative functors can be seen as a generalization from
128+ lifting unary functions (`fmap`) to lifting functions of arbitrary arity:
129+ `pure x` is a lifting of an 0-ary function `x`; `liftA2` (read as lift
130+ applicative binary) lifts binary functions, and each and every `liftAN` can
131+ be written out in terms of `pure` and `(<*>)`:
132+
133+```haskell ignore
134+liftA1 :: Applicative f => (a -> b) -> f a -> f b
135+liftA1 g fa = pure g <*> fa
136+
137+(<$>) :: Applicative f => (a -> b) -> f a -> f b
138+(<$>) = liftA1
139+
140+liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
141+liftA2 g fa fb = g <$> fa <*> fb
142+
143+liftA3 ::
144+ Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
145+liftA3 g fa fb fc = g <$> fa <*> fb <*> fc
146+```
147+
148+ Note that in doing so we showed that every applicative functor (that is,
149+ a type implementing `pure` and `(<*>)`) is a functor.
150+
151+* On the other hand, applicative functor is a functor which can __apply__
152+ functions from inside of it via `(<*>)`, here's why it is called an
153+ __Applicative__.
154+
155+If `liftA2` can be implemented using `pure` and `(<*>)`, why is it included in
156+the class declaration? The reason for this is that `(<*>)` can be implemented
157+using `liftA2`:
158+
159+```haskell ignore
160+(<*>) :: Applicative f => f (a -> b) -> f a -> f b
161+(<*>) = liftA2 (\g x -> g x)
162+```
163+
164+Applicative laws:
165+
166+1. `pure id <*> v = v` (Identity);
167+2. `pure f <*> pure x = pure (v x)` (Homomorphism);
168+3. `u <*> pure y = pure (\f -> f y) <*> u` (Interchange);
169+4. `u <*> (v <*> w) = ((pure (.) <*> u) <*> v) <*> w` (Composition);
170+5. `liftA2 g u v = pure g <*> u <*> v` (relation with `liftA2`);
171+6. `fmap = liftA1` (relation with Functor).
172+
173+Intuitively:
174+
175+* `pure` must not provide any additional information meaningful to `(<*>)` (so
176+ here's the source of the name: it should encapsulate a __pure__ value and do
177+ nothing more);
178+* the merging of internal structure performed in `(<*>)` should be associative.
179+
180+__Exercise 6__: show that functor laws hold automatically for every lawful
181+applicative.
182+
183+### Monad
184+
185+Now, the most notable typeclass of all is a Monad. What is this?
186+
187+```haskell ignore
188+class Applicative m => Monad m where
189+ return :: a -> m a
190+ return = pure
191+
192+ (>>=) :: m a -> (a -> m b) -> m b
193+
194+ (>>) :: m a -> m b -> m b
195+ mx >> my = mx >>= (\_ -> my)
196+```
197+
198+As we mentioned before, this is an interface most useful to express effectful
199+operations: `return x` is a pure result of otherwise effectful computation;
200+`(>>=)` and `(>>)` both execute operations in order, where in `(>>=)` (also
201+called "bind") a second computation can depend on the outcome of the first.
202+
203+Turns out that it is a proper subclass of Applicative, meaning that `(<*>)` can
204+be written out in terms of `return` and `(>>=)`:
205+
206+```haskell
207+ap :: Monad m => m (a -> b) -> m a -> m b
208+ap mf mx = mf >>= \f -> mx >>= \x -> return (f x)
209+```
210+
211+(This is already defined in standard library, in module `Control.Monad`. Don't
212+be afraid to use Hoogle to find such combinators!)
213+
214+A little insight into the way these typeclasses could be discovered. Starting
215+from `Functor f`, every class introduces new capabilities for lifting of
216+functions into `f`:
217+
218+* `fmap` is `(a -> b)` to `(f a -> f b)`
219+* `(<*>)` is `f (a -> b)` to `(f a -> f b)`
220+* `flip (>>=)` is `(a -> f b)` to `(f a -> f b)`
221+
222+`(f a -> f b)` to `(f a -> f b)` is `id`; what about this?
223+
224+```haskell ignore
225+whatIsThis :: (f a -> b) -> (f a -> f b)
226+```
227+
228+Actually, this is a method from `Comonad` interface, which has its own
229+interesting applications. However, they are out of scope for now.
230+
231+Monad laws:
232+
233+1. `return a >>= k = k a` (Left identity);
234+2. `m >>= return = m` (Right identity);
235+3. `(m >>= k) >>= h = m >>= (\x -> k x >>= h)` (Associativity).
236+
237+After squinting a little, this looks like monoid laws. With additional
238+technical work, Monad actually looks like a proper "monoid in the category of
239+endofunctors", whatever this category-theoretic talk means. However, you do not
240+need this arcane knowledge to program in Haskell: just learn the laws and the
241+interface itself.
242+
243+# Exercise solutions
244+
245+```haskell
246+foldList :: Monoid a => [a] -> a
247+foldList [] = mempty
248+foldList (x : xs) = x <> foldList xs
249+
250+instance Num a => Semigroup (Sum a) where
251+ Sum x <> Sum y = Sum (x + y)
252+
253+instance Num a => Monoid (Sum a) where
254+ mempty = Sum 0
255+
256+instance Num a => Semigroup (Mul a) where
257+ Mul x <> Mul y = Mul (x * y)
258+
259+instance Num a => Monoid (Mul a) where
260+ mempty = Mul 1
261+
262+sumList :: Num a => [a] -> a
263+sumList = getSum . foldList . map Sum
264+
265+productList :: Num a => [a] -> a
266+productList = getMul . foldList . map Mul
267+
268+instance Foldable BinTree where
269+ foldMap _ Leaf = mempty
270+ foldMap f (Branch l x r) = foldMap f l <> f x <> foldMap f r
271+
272+instance Functor BinTree where
273+ fmap _ Leaf = Leaf
274+ fmap f (Branch l x r) = Branch (fmap f l) (f x) (fmap f r)
275+```
276+
277+Solution for __Exercise 6__:
278+
279+```haskell ignore
280+fmap id x = liftA1 id x = pure id <*> x = x
281+
282+fmap g (fmap f x) = liftA1 g (liftA1 f x)
283+ = pure g <*> (pure f <*> x)
284+ = ((pure (.) <*> pure g) <*> pure f) <*> x
285+ = (pure ((.) g) <*> pure f) <*> x
286+ = pure ((.) g f) <*> x
287+ = pure (g . f) <*> x
288+ = liftA1 (g . f) x
289+ = fmap (g . f) x
290+```