fix: use fenced blocks for code
This commit is contained in:
		@@ -1,20 +1,20 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
layout: post
 | 
					layout: post
 | 
				
			||||||
title:  "Typoclassopedia: Exercise solutions"
 | 
					title:  "Typoclassopedia: Exercise solutions"
 | 
				
			||||||
date:   2017-09-27 12:12:12
 | 
					date:   2017-09-27 
 | 
				
			||||||
permalink: typoclassopedia-exercise-solutions/
 | 
					permalink: typoclassopedia-exercise-solutions/
 | 
				
			||||||
categories: programming
 | 
					categories: programming
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
I wanted to get proficient in Haskell so I decided to follow [An [Essential] Haskell Reading List][http://www.stephendiehl.com/posts/essential_haskell.html], there I stumbled upon Typoclassopedia, while the material is great, I couldn't find solutions for the exercises to check against, so I decided I would write my own and hopefully the solutions would get fixed in case I have gone wrong by others. So if you think a solution is wrong, let me know in the comments!
 | 
					I wanted to get proficient in Haskell so I decided to follow [An [Essential] Haskell Reading List](http://www.stephendiehl.com/posts/essential_haskell.html), there I stumbled upon [Typoclassopedia](https://wiki.haskell.org/Typeclassopedia), while the material is great, I couldn't find solutions for the exercises to check against, so I decided I would write my own and hopefully the solutions would get fixed in case I have gone wrong by others. So if you think a solution is wrong, let me know in the comments!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In each section below, I left some reference material for the exercises and then the solutions.
 | 
					In each section below, I left some reference material for the exercises and then the solutions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Functor
 | 
					Functor
 | 
				
			||||||
==========
 | 
					==========
 | 
				
			||||||
### Instances
 | 
					## Instances
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					```haskell
 | 
				
			||||||
instance Functor [] where
 | 
					instance Functor [] where
 | 
				
			||||||
  fmap :: (a -> b) -> [a] -> [b]
 | 
					  fmap :: (a -> b) -> [a] -> [b]
 | 
				
			||||||
  fmap _ []     = []
 | 
					  fmap _ []     = []
 | 
				
			||||||
@@ -25,145 +25,145 @@ instance Functor Maybe where
 | 
				
			|||||||
  fmap :: (a -> b) -> Maybe a -> Maybe b
 | 
					  fmap :: (a -> b) -> Maybe a -> Maybe b
 | 
				
			||||||
  fmap _ Nothing  = Nothing
 | 
					  fmap _ Nothing  = Nothing
 | 
				
			||||||
  fmap g (Just a) = Just (g a)
 | 
					  fmap g (Just a) = Just (g a)
 | 
				
			||||||
{% endhighlight %}
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> ((,) e) represents a container which holds an “annotation” of type e along with the actual value it holds. It might be clearer to write it as (e,), by analogy with an operator section like (1+), but that syntax is not allowed in types (although it is allowed in expressions with the TupleSections extension enabled). However, you can certainly think of it as (e,). 
 | 
					> ((,) e) represents a container which holds an “annotation” of type e along with the actual value it holds. It might be clearer to write it as (e,), by analogy with an operator section like (1+), but that syntax is not allowed in types (although it is allowed in expressions with the TupleSections extension enabled). However, you can certainly think of it as (e,). 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> ((->) e) (which can be thought of as (e ->); see above), the type of functions which take a value of type e as a parameter, is a Functor. As a container, (e -> a) represents a (possibly infinite) set of values of a, indexed by values of e. Alternatively, and more usefully, ((->) e) can be thought of as a context in which a value of type e is available to be consulted in a read-only fashion. This is also why ((->) e) is sometimes referred to as the reader monad; more on this later. 
 | 
					> ((->) e) (which can be thought of as (e ->); see above), the type of functions which take a value of type e as a parameter, is a Functor. As a container, (e -> a) represents a (possibly infinite) set of values of a, indexed by values of e. Alternatively, and more usefully, ((->) e) can be thought of as a context in which a value of type e is available to be consulted in a read-only fashion. This is also why ((->) e) is sometimes referred to as the reader monad; more on this later. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Exercises
 | 
					### Exercises
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Implement `Functor` instances for `Either e` and `((->) e)`.
 | 
					 1. Implement `Functor` instances for `Either e` and `((->) e)`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Solution**:
 | 
					    **Solution**:
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
instance Functor (Either e) where
 | 
					    instance Functor (Either e) where
 | 
				
			||||||
  fmap _ (Left e) = Left e
 | 
					      fmap _ (Left e) = Left e
 | 
				
			||||||
  fmap g (Right a) = Right (g a)
 | 
					      fmap g (Right a) = Right (g a)
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
instance Functor ((->) e) where
 | 
					    instance Functor ((->) e) where
 | 
				
			||||||
  fmap g f = g . f
 | 
					      fmap g f = g . f
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2. Implement `Functor` instances for `((,) e)` and for `Pair`, defined as `data Pair a = Pair a a`. Explain their similarities and differences.
 | 
					 2. Implement `Functor` instances for `((,) e)` and for `Pair`, defined as below. Explain their similarities and differences.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Solution**:
 | 
					    **Solution**:
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
instance Functor ((,) e) where
 | 
					    instance Functor ((,) e) where
 | 
				
			||||||
  fmap g (a, b) = (a, g b) 
 | 
					      fmap g (a, b) = (a, g b) 
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
data Pair a = Pair a a
 | 
					    data Pair a = Pair a a
 | 
				
			||||||
instance Functor Pair where
 | 
					    instance Functor Pair where
 | 
				
			||||||
  fmap g (Pair a b) = Pair (g a) (g b)
 | 
					      fmap g (Pair a b) = Pair (g a) (g b)
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Their similarity is in the fact that they both represent types of two values.
 | 
					    Their similarity is in the fact that they both represent types of two values.
 | 
				
			||||||
Their difference is that `((,) e)` (tuples of two) can have values of different types (kind of `(,)` is `* -> *`) while both values of `Pair` have the same type `a`, so `Pair` has kind `*`.
 | 
					    Their difference is that `((,) e)` (tuples of two) can have values of different types (kind of `(,)` is `* -> *`) while both values of `Pair` have the same type `a`, so `Pair` has kind `*`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
3. Implement a `Functor` instance for the type `ITree`, defined as
 | 
					3. Implement a `Functor` instance for the type `ITree`, defined as
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
data ITree a = Leaf (Int -> a)
 | 
					    data ITree a = Leaf (Int -> a)
 | 
				
			||||||
             | Node [ITree a]
 | 
					                | Node [ITree a]
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Solution**:
 | 
					    **Solution**:
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
instance Functor ITree where
 | 
					    instance Functor ITree where
 | 
				
			||||||
  fmap g (Leaf f) = Leaf (g . f)
 | 
					      fmap g (Leaf f) = Leaf (g . f)
 | 
				
			||||||
  fmap g (Node xs) = Node (fmap (fmap g) xs)
 | 
					      fmap g (Node xs) = Node (fmap (fmap g) xs)
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To test this instance, I defined a function to apply the tree to an `Int`:
 | 
					    To test this instance, I defined a function to apply the tree to an `Int`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
applyTree :: ITree a -> Int -> [a]
 | 
					    applyTree :: ITree a -> Int -> [a]
 | 
				
			||||||
applyTree (Leaf g) i = [g i]
 | 
					    applyTree (Leaf g) i = [g i]
 | 
				
			||||||
applyTree (Node []) _ = []
 | 
					    applyTree (Node []) _ = []
 | 
				
			||||||
applyTree (Node (x:xs)) i = applyTree x i ++ applyTree (Node xs) i
 | 
					    applyTree (Node (x:xs)) i = applyTree x i ++ applyTree (Node xs) i
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is not a standard tree traversing algorithm, I just wanted it to be simple for testing.
 | 
					    This is not a standard tree traversing algorithm, I just wanted it to be simple for testing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Now test the instance:
 | 
					    Now test the instance:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
λ: let t = Node [Node [Leaf (+5), Leaf (+1)], Leaf (*2)]
 | 
					    λ: let t = Node [Node [Leaf (+5), Leaf (+1)], Leaf (*2)]
 | 
				
			||||||
λ: applyTree t 1
 | 
					    λ: applyTree t 1
 | 
				
			||||||
[6,2,2]
 | 
					    [6,2,2]
 | 
				
			||||||
λ: applyTree (fmap id t) 1
 | 
					    λ: applyTree (fmap id t) 1
 | 
				
			||||||
[6,2,2]
 | 
					    [6,2,2]
 | 
				
			||||||
λ: applyTree (fmap (+10) t) 1
 | 
					    λ: applyTree (fmap (+10) t) 1
 | 
				
			||||||
[16, 12, 12]
 | 
					    [16, 12, 12]
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
4. Give an example of a type of kind `* -> *` which cannot be made an instance of `Functor` (without using `undefined`).
 | 
					4. Give an example of a type of kind `* -> *` which cannot be made an instance of `Functor` (without using `undefined`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
I don't know the answer to this one yet!
 | 
					    I don't know the answer to this one yet!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
6. Is this statement true or false?
 | 
					6. Is this statement true or false?
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
> The composition of two `Functor`s is also a `Functor`.
 | 
					    > The composition of two `Functor`s is also a `Functor`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If false, give a counterexample; if true, prove it by exhibiting some appropriate Haskell code.
 | 
					    If false, give a counterexample; if true, prove it by exhibiting some appropriate Haskell code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Solution**:
 | 
					    **Solution**:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
It's true, and can be proved by the following function:
 | 
					    It's true, and can be proved by the following function:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
ffmap :: (Functor f, Functor j) => (a -> b) -> f (j a) -> f (j b)
 | 
					    ffmap :: (Functor f, Functor j) => (a -> b) -> f (j a) -> f (j b)
 | 
				
			||||||
ffmap g = fmap (fmap g)
 | 
					    ffmap g = fmap (fmap g)
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can test this on arbitrary compositions of `Functor`s:
 | 
					    You can test this on arbitrary compositions of `Functor`s:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
main = do
 | 
					    main = do
 | 
				
			||||||
  let result :: Maybe (Either String Int) = ffmap (+ 2) (Just . Right $ 5)
 | 
					      let result :: Maybe (Either String Int) = ffmap (+ 2) (Just . Right $ 5)
 | 
				
			||||||
  print result -- (Just (Right 7))
 | 
					      print result -- (Just (Right 7))
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Functor Laws
 | 
					## Functor Laws
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					```haskell
 | 
				
			||||||
fmap id = id
 | 
					fmap id = id
 | 
				
			||||||
fmap (g . h) = (fmap g) . (fmap h)
 | 
					fmap (g . h) = (fmap g) . (fmap h)
 | 
				
			||||||
{% endhighlight %}
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Exercises
 | 
					### Exercises
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Although it is not possible for a Functor instance to satisfy the first Functor law but not the second (excluding undefined), the reverse is possible. Give an example of a (bogus) Functor instance which satisfies the second law but not the first. 
 | 
					1. Although it is not possible for a Functor instance to satisfy the first Functor law but not the second (excluding undefined), the reverse is possible. Give an example of a (bogus) Functor instance which satisfies the second law but not the first. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Solution**:
 | 
					    **Solution**:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This is easy, consider this instance:
 | 
					    This is easy, consider this instance:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
instance Functor [] where
 | 
					    instance Functor [] where
 | 
				
			||||||
  fmap _ [] = [1]
 | 
					      fmap _ [] = [1]
 | 
				
			||||||
  fmap g (x:xs) = g x: fmap g xs
 | 
					      fmap g (x:xs) = g x: fmap g xs
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Then, you can test the first and second laws:
 | 
					    Then, you can test the first and second laws:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
λ: fmap id [] -- [1], breaks the first law
 | 
					    λ: fmap id [] -- [1], breaks the first law
 | 
				
			||||||
λ: fmap ((+1) . (+2)) [1,2] -- [4, 5], second law holds
 | 
					    λ: fmap ((+1) . (+2)) [1,2] -- [4, 5], second law holds
 | 
				
			||||||
λ: fmap (+1) . fmap (+2) $ [1,2] -- [4, 5]
 | 
					    λ: fmap (+1) . fmap (+2) $ [1,2] -- [4, 5]
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Which laws are violated by the evil Functor instance for list shown above: both laws, or the first law alone? Give specific counterexamples. 
 | 
					2. Which laws are violated by the evil Functor instance for list shown above: both laws, or the first law alone? Give specific counterexamples. 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% highlight haskell %}
 | 
					    ```haskell
 | 
				
			||||||
-- Evil Functor instance
 | 
					    -- Evil Functor instance
 | 
				
			||||||
instance Functor [] where
 | 
					    instance Functor [] where
 | 
				
			||||||
  fmap :: (a -> b) -> [a] -> [b]
 | 
					      fmap :: (a -> b) -> [a] -> [b]
 | 
				
			||||||
  fmap _ [] = []
 | 
					      fmap _ [] = []
 | 
				
			||||||
  fmap g (x:xs) = g x : g x : fmap g xs
 | 
					      fmap g (x:xs) = g x : g x : fmap g xs
 | 
				
			||||||
{% endhighlight %}
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Solution**:
 | 
					    **Solution**:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The instance defined breaks the first law (`fmap id [1] -- [1,1]`), but holds for the second law.
 | 
					    The instance defined breaks the first law (`fmap id [1] -- [1,1]`), but holds for the second law.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -138,7 +138,7 @@ code {
 | 
				
			|||||||
    font-size: 15px;
 | 
					    font-size: 15px;
 | 
				
			||||||
    border: 1px solid $grey-color-light;
 | 
					    border: 1px solid $grey-color-light;
 | 
				
			||||||
    border-radius: 3px;
 | 
					    border-radius: 3px;
 | 
				
			||||||
    background-color: #eef;
 | 
					    background-color: white;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
code {
 | 
					code {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user