From 03235504bae69a76574b51498ff4a13fa89eee42 Mon Sep 17 00:00:00 2001 From: Mahdi Dibaiee Date: Wed, 27 Sep 2017 13:31:28 +0330 Subject: [PATCH] fix: use fenced blocks for code --- ...-09-27-typoclassopedia-exercise-answers.md | 198 +++++++++--------- _sass/_base.scss | 4 +- 2 files changed, 101 insertions(+), 101 deletions(-) diff --git a/_posts/2017-09-27-typoclassopedia-exercise-answers.md b/_posts/2017-09-27-typoclassopedia-exercise-answers.md index 6c10585..1eea5eb 100644 --- a/_posts/2017-09-27-typoclassopedia-exercise-answers.md +++ b/_posts/2017-09-27-typoclassopedia-exercise-answers.md @@ -1,20 +1,20 @@ --- layout: post title: "Typoclassopedia: Exercise solutions" -date: 2017-09-27 12:12:12 +date: 2017-09-27 permalink: typoclassopedia-exercise-solutions/ 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. Functor ========== -### Instances +## Instances -{% highlight haskell %} +```haskell instance Functor [] where fmap :: (a -> b) -> [a] -> [b] fmap _ [] = [] @@ -25,145 +25,145 @@ instance Functor Maybe where fmap :: (a -> b) -> Maybe a -> Maybe b fmap _ Nothing = Nothing 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) (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**: -{% highlight haskell %} -instance Functor (Either e) where - fmap _ (Left e) = Left e - fmap g (Right a) = Right (g a) - -instance Functor ((->) e) where - fmap g f = g . f -{% endhighlight %} + **Solution**: + ```haskell + instance Functor (Either e) where + fmap _ (Left e) = Left e + fmap g (Right a) = Right (g a) + + instance Functor ((->) e) where + fmap g f = g . f + ``` -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**: -{% highlight haskell %} -instance Functor ((,) e) where - fmap g (a, b) = (a, g b) - - -data Pair a = Pair a a -instance Functor Pair where - fmap g (Pair a b) = Pair (g a) (g b) -{% endhighlight %} + **Solution**: + ```haskell + instance Functor ((,) e) where + fmap g (a, b) = (a, g b) + + + data Pair a = Pair a a + instance Functor Pair where + fmap g (Pair a b) = Pair (g a) (g b) + ``` -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 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 `*`. 3. Implement a `Functor` instance for the type `ITree`, defined as -{% highlight haskell %} -data ITree a = Leaf (Int -> a) - | Node [ITree a] -{% endhighlight %} + ```haskell + data ITree a = Leaf (Int -> a) + | Node [ITree a] + ``` -**Solution**: -{% highlight haskell %} -instance Functor ITree where - fmap g (Leaf f) = Leaf (g . f) - fmap g (Node xs) = Node (fmap (fmap g) xs) -{% endhighlight %} + **Solution**: + ```haskell + instance Functor ITree where + fmap g (Leaf f) = Leaf (g . f) + fmap g (Node xs) = Node (fmap (fmap g) xs) + ``` -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 %} -applyTree :: ITree a -> Int -> [a] -applyTree (Leaf g) i = [g i] -applyTree (Node []) _ = [] -applyTree (Node (x:xs)) i = applyTree x i ++ applyTree (Node xs) i -{% endhighlight %} + ```haskell + applyTree :: ITree a -> Int -> [a] + applyTree (Leaf g) i = [g i] + applyTree (Node []) _ = [] + applyTree (Node (x:xs)) i = applyTree x i ++ applyTree (Node xs) i + ``` -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 %} -λ: let t = Node [Node [Leaf (+5), Leaf (+1)], Leaf (*2)] -λ: applyTree t 1 -[6,2,2] -λ: applyTree (fmap id t) 1 -[6,2,2] -λ: applyTree (fmap (+10) t) 1 -[16, 12, 12] -{% endhighlight %} + ```haskell + λ: let t = Node [Node [Leaf (+5), Leaf (+1)], Leaf (*2)] + λ: applyTree t 1 + [6,2,2] + λ: applyTree (fmap id t) 1 + [6,2,2] + λ: applyTree (fmap (+10) t) 1 + [16, 12, 12] + ``` 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? -> 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 %} -ffmap :: (Functor f, Functor j) => (a -> b) -> f (j a) -> f (j b) -ffmap g = fmap (fmap g) -{% endhighlight %} + ```haskell + ffmap :: (Functor f, Functor j) => (a -> b) -> f (j a) -> f (j b) + ffmap g = fmap (fmap g) + ``` -You can test this on arbitrary compositions of `Functor`s: + You can test this on arbitrary compositions of `Functor`s: -{% highlight haskell %} -main = do - let result :: Maybe (Either String Int) = ffmap (+ 2) (Just . Right $ 5) - print result -- (Just (Right 7)) -{% endhighlight %} + ```haskell + main = do + let result :: Maybe (Either String Int) = ffmap (+ 2) (Just . Right $ 5) + print result -- (Just (Right 7)) + ``` -### Functor Laws +## Functor Laws -{% highlight haskell %} +```haskell fmap id = id 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. -**Solution**: + **Solution**: -This is easy, consider this instance: + This is easy, consider this instance: -{% highlight haskell %} -instance Functor [] where - fmap _ [] = [1] - fmap g (x:xs) = g x: fmap g xs -{% endhighlight %} + ```haskell + instance Functor [] where + fmap _ [] = [1] + fmap g (x:xs) = g x: fmap g xs + ``` -Then, you can test the first and second laws: + Then, you can test the first and second laws: -{% highlight haskell %} -λ: fmap id [] -- [1], breaks the first law -λ: fmap ((+1) . (+2)) [1,2] -- [4, 5], second law holds -λ: fmap (+1) . fmap (+2) $ [1,2] -- [4, 5] -{% endhighlight %} + ```haskell + λ: fmap id [] -- [1], breaks the first law + λ: fmap ((+1) . (+2)) [1,2] -- [4, 5], second law holds + λ: fmap (+1) . fmap (+2) $ [1,2] -- [4, 5] + ``` -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 %} --- Evil Functor instance -instance Functor [] where - fmap :: (a -> b) -> [a] -> [b] - fmap _ [] = [] - fmap g (x:xs) = g x : g x : fmap g xs -{% endhighlight %} + ```haskell + -- Evil Functor instance + instance Functor [] where + fmap :: (a -> b) -> [a] -> [b] + fmap _ [] = [] + fmap g (x:xs) = g x : g x : fmap g xs + ``` -**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. diff --git a/_sass/_base.scss b/_sass/_base.scss index 72ecd63..dc81032 100644 --- a/_sass/_base.scss +++ b/_sass/_base.scss @@ -138,7 +138,7 @@ code { font-size: 15px; border: 1px solid $grey-color-light; border-radius: 3px; - background-color: #eef; + background-color: white; } code { @@ -227,4 +227,4 @@ pre { @font-face { font-family: 'Ubuntu Mono'; src: url(fonts/UbuntuMono-Regular_gdi.woff); -} \ No newline at end of file +}