### Types ![Dali, the madonna of port Lligat](http://yannesposito.com/Scratch/img/blog/Haskell-the-Hard-Way/salvador-dali-the-madonna-of-port-lligat.jpg) --- Too long; didn't read: - `type Name = AnotherType` is just an alias and the compiler doesn't do any difference between `Name` and `AnotherType`. - `data Name = NameConstructor AnotherType` make a difference. - `data` can construct structures which can be recursives. - `deriving` is magic and create functions for you. --- In Haskell, types are strong and static. Why is this important? It will help you _greatly_ to avoid mistakes. In Haskell, most bugs are caught during the compilation of your program. And the main reason is because of the type inference during compilation. It will be easy to detect where you used the wrong parameter at the wrong place for example. #### Type inference Static typing is generally essential to reach fast execution time. But most statically typed languages are bad at generalizing concepts. Haskell's saving grace is that it can _infer_ types. Here is a simple example. The `square` function in Haskell: ``` haskell square x = x * x ``` This function can `square` any Numeral type. You can provide `square` with an `Int`, an `Integer`, a `Float` a `Fractional` and even `Complex`. Proof by example: ``` active haskell import Data.Complex square x = x*x main = do print $ square 2 print $ square 2.1 print $ square (2 :+ 1) ``` `x :+ y` is the notation for the complex (x + ib). Now compare with the amount of code necessary in C: ``` c int int_square(int x) { return x*x; } float float_square(float x) {return x*x; } complex complex_square (complex z) { complex tmp; tmp.real = z.real * z.real - z.img * z.img; tmp.img = 2 * z.img * z.real; } complex x,y; y = complex_square(x); ``` For each type, you need to write a new function. The only way to work around this problem is to use some meta-programming trick. For example using the pre-processor. In C++ there is a better way, the C++ templates: ``` c++ #include #include using namespace std; template T square(T x) { return x*x; } int main() { // int int sqr_of_five = square(5); cout << sqr_of_five << endl; // double cout << (double)square(5.3) << endl; // complex cout << square( complex(5,3) ) << endl; return 0; } ``` C++ does a far better job than C. For more complex function the syntax can be hard to follow: look at [this article](http://bartoszmilewski.com/2009/10/21/what-does-haskell-have-to-do-with-c/) for example. In C++ you must declare that a function can work with different types. In Haskell this is the opposite. The function will be as general as possible by default. Type inference gives Haskell the feeling of freedom that dynamically typed languages provide. But unlike dynamically typed languages, most errors are caught before the execution. Generally, in Haskell: > "if it compiles it certainly does what you intended" #### Type construction You can construct your own types. First you can use aliases or type synonyms. ``` active haskell type Name = String type Color = String showInfos :: Name -> Color -> String showInfos name color = "Name: " ++ name ++ ", Color: " ++ color name :: Name name = "Robin" color :: Color color = "Blue" main = putStrLn $ showInfos name color ``` But it doesn't protect you much. Try to swap the two parameter of `showInfos` and run the program: ``` active haskell type Name = String type Color = String showInfos :: Name -> Color -> String showInfos name color = "Name: " ++ name ++ ", Color: " ++ color name :: Name name = "Robin" color :: Color color = "Blue" -- show main = putStrLn $ showInfos color name -- /show ``` It will compile and execute. In fact you can replace Name, Color and String everywhere. The compiler will treat them as completely identical. Another method is to create your own types using the keyword `data`. ``` active haskell data Name = NameConstr String data Color = ColorConstr String showInfos :: Name -> Color -> String showInfos (NameConstr name) (ColorConstr color) = "Name: " ++ name ++ ", Color: " ++ color name = NameConstr "Robin" color = ColorConstr "Blue" main = putStrLn $ showInfos name color ``` Now if you switch parameters of `showInfos`, the compiler complains! A possible mistake you could never do again. The only price is to be more verbose. Also remark constructor are functions: ``` haskell NameConstr :: String -> Name ColorConstr :: String -> Color ``` The syntax of `data` is mainly: ``` haskell data TypeName = ConstructorName [types] | ConstructorName2 [types] | ... ``` Generally the usage is to use the same name for the DataTypeName and DataTypeConstructor. Example: ``` haskell data Complex a = Num a => Complex a a ``` Also you can use the record syntax: ``` haskell data DataTypeName = DataConstructor { field1 :: [type of field1] , field2 :: [type of field2] ... , fieldn :: [type of fieldn] } ``` And many accessors are made for you. Furthermore you can use another order when setting values. Example: ``` haskell data Complex a = Num a => Complex { real :: a, img :: a} c = Complex 1.0 2.0 z = Complex { real = 3, img = 4 } real c ⇒ 1.0 img z ⇒ 4 ``` ##### Exercises: 1) Declare the data type `Knight` in the following program: ``` active haskell data Knight = undefined galaad = Knight { name = "Galaad, the pure" , quest = "To seek the Holy Grail" , favoriteColor = "The blue... No the red! AAAAAAHHHHHHH!!!!" } showCharacter :: Knight -> String showCharacter knight = "What is your name?\n" ++ "My name is " ++ name knight ++ "\nWhat is your quest?\n" ++ quest knight ++ "\nWhat is your favorite color?\n" ++ favoriteColor knight main = do putStrLn $ showCharacter galaad ``` @@@ Solution ``` active haskell data Knight = {-hi-}Knight { name :: String , quest :: String , favoriteColor :: String }{-/hi-} galaad = Knight { name = "Galaad, the pure" , quest = "To seek the Holy Grail" , favoriteColor = "The blue... No the red! AAAAAAHHHHHHH!!!!" } showCharacter :: Knight -> String showCharacter knight = "What is your name?\n" ++ "My name is " ++ name knight ++ "\nWhat is your quest?\n" ++ quest knight ++ "\nWhat is your favorite color?\n" ++ favoriteColor knight main = do putStrLn $ showCharacter galaad ``` @@@ 2) Somebody changed the showCharacter to make it more readable. Unfortunately he mades some mistake. Change the type declaration such that the compiler complains, and then correct the showCharacter function. ``` active haskell data Knight = Knight { name :: String , quest :: String , favoriteColor :: String } showNameQuestion :: String -> String showNameQuestion someName = "What is your name? My name is " ++ someName showQuestQuestion :: String -> String showQuestQuestion someQuest = "What is your quest? " ++ someQuest showColorQuestion :: String -> String showColorQuestion someColor = "What is your favorite color? " ++ someColor showCharacter :: Knight -> String showCharacter knight = showNameQuestion (favoriteColor knight) ++ "\n" ++ showQuestQuestion (name knight ) ++ "\n" ++ showColorQuestion (quest knight) galaad = Knight { name = "Galaad, the pure" , quest = "To seek the Holy Grail" , favoriteColor = "The blue... No the red! AAAAAAHHHHHHH!!!!" } main = do putStrLn $ showCharacter galaad ``` @@@ Solution ``` active haskell {-hi-}data Name = Name String data Quest = Quest String data Color = Color String{-/hi-} data Knight = Knight { name :: Name , quest :: Quest , favoriteColor :: Color } showNameQuestion :: {-hi-}Name{-/hi-} -> String showNameQuestion {-hi-}(Name someName){-/hi-} = "What is your name? My name is " ++ someName showQuestQuestion :: {-hi-}Quest{-/hi-} -> String showQuestQuestion {-hi-}(Quest someQuest){-/hi-} = "What is your quest? " ++ someQuest showColorQuestion :: {-hi-}Color{-/hi-} -> String showColorQuestion {-hi-}(Color someColor){-/hi-} = "What is your favorite color? " ++ someColor showCharacter :: Knight -> String {- -- This version doesn't compile, try to uncomment to verify showCharacter knight = showNameQuestion (favoriteColor knight) ++ "\n" ++ showQuestQuestion (name knight ) ++ "\n" ++ showColorQuestion (quest knight) -} showCharacter knight = showNameQuestion (name knight) ++ "\n" ++ showQuestQuestion (quest knight ) ++ "\n" ++ showColorQuestion (favoriteColor knight) galaad = Knight { name = {-hi-}Name{-/hi-} "Galaad, the pure" , quest = {-hi-}Quest{-/hi-} "To seek the Holy Grail" , favoriteColor = {-hi-}Color{-/hi-} "The blue... No the red! AAAAAAHHHHHHH!!!!" } main = do putStrLn $ showCharacter galaad ``` @@@ #### Recursive type You already encountered a recursive type: lists. You can re-create lists, but with a more verbose syntax: ``` haskell data List a = Empty | Cons a (List a) ``` If you really want to use an easier syntax you can use an infix name for constructors. ``` haskell infixr 5 ::: data List a = Nil | a ::: (List a) ``` The number after `infixr` is the priority. If you want to be able to print (`Show`), read (`Read`), test equality (`Eq`) and compare (`Ord`) your new data structure you can tell Haskell to derive the appropriate functions for you. ``` haskell infixr 5 ::: data List a = Nil | a ::: (List a) deriving (Show,Read,Eq,Ord) ``` When you add `deriving (Show)` to your data declaration, Haskell create a `show` function for you. We'll see soon how you can use your own `show` function. ``` haskell convertList [] = Nil convertList (x:xs) = x ::: convertList xs ``` ``` active haskell infixr 5 ::: data List a = Nil | a ::: (List a) deriving (Show,Read,Eq,Ord) convertList [] = Nil convertList (x:xs) = x ::: convertList xs -- show main = do print (0 ::: 1 ::: Nil) print (convertList [0,1]) -- /show ``` #### Trees ![Magritte, l'Arbre](http://yannesposito.com/Scratch/img/blog/Haskell-the-Hard-Way/magritte-l-arbre.jpg) We'll just give another standard example: binary trees. ``` haskell import Data.List data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Show) ``` We will also create a function which turns a list into an ordered binary tree. ``` haskell treeFromList :: (Ord a) => [a] -> BinTree a treeFromList [] = Empty treeFromList (x:xs) = Node x (treeFromList (filter (x) xs)) ``` Look at how elegant this function is. In plain English: - an empty list will be converted to an empty tree. - a list `(x:xs)` will be converted to a tree where: - The root is `x` - Its left subtree is the tree created from members of the list `xs` which are strictly inferior to `x` and - the right subtree is the tree created from members of the list `xs` which are strictly superior to `x`. ``` active haskell import Data.List data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Show) treeFromList :: (Ord a) => [a] -> BinTree a treeFromList [] = Empty treeFromList (x:xs) = Node x (treeFromList (filter (x) xs)) -- show main = print $ treeFromList [7,2,4,8] -- /show ``` This is an informative but quite unpleasant representation of our tree. Just for fun, let's code a better display for our trees. I simply had fun making a nice function to display trees in a general way. You can safely skip this part if you find it too difficult to follow. We have a few changes to make. We remove the `deriving (Show)` from the declaration of our `BinTree` type. And it might also be useful to make our BinTree an instance of (`Eq` and `Ord`). We will be able to test equality and compare trees. ``` haskell data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Eq,Ord) ``` Without the `deriving (Show)`, Haskell doesn't create a `show` method for us. We will create our own version of `show`. To achieve this, we must declare that our newly created type `BinTree a` is an instance of the type class `Show`. The general syntax is: ``` haskell instance Show (BinTree a) where show t = ... -- You declare your function here ``` Here is my version of how to show a binary tree. Don't worry about the apparent complexity. I made a lot of improvements in order to display even stranger objects. ``` haskell -- declare BinTree a to be an instance of Show instance (Show a) => Show (BinTree a) where -- will start by a '<' before the root -- and put a : a begining of line show t = "< " ++ replace '\n' "\n: " (treeshow "" t) where -- treeshow pref Tree -- shows a tree and starts each line with pref -- We don't display the Empty tree treeshow pref Empty = "" -- Leaf treeshow pref (Node x Empty Empty) = (pshow pref x) -- Right branch is empty treeshow pref (Node x left Empty) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " left) -- Left branch is empty treeshow pref (Node x Empty right) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " right) -- Tree with left and right children non empty treeshow pref (Node x left right) = (pshow pref x) ++ "\n" ++ (showSon pref "|--" "| " left) ++ "\n" ++ (showSon pref "`--" " " right) -- shows a tree using some prefixes to make it nice showSon pref before next t = pref ++ before ++ treeshow (pref ++ next) t -- pshow replaces "\n" by "\n"++pref pshow pref x = replace '\n' ("\n"++pref) (show x) -- replaces one char by another string replace c new string = concatMap (change c new) string where change c new x | x == c = new | otherwise = x:[] -- "x" ``` The `treeFromList` method remains identical. ``` haskell treeFromList :: (Ord a) => [a] -> BinTree a treeFromList [] = Empty treeFromList (x:xs) = Node x (treeFromList (filter (x) xs)) ``` And now, we can play: ``` active haskell data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Eq,Ord) -- declare BinTree a to be an instance of Show instance (Show a) => Show (BinTree a) where -- will start by a '<' before the root -- and put a : a begining of line show t = "< " ++ replace '\n' "\n: " (treeshow "" t) where -- treeshow pref Tree -- shows a tree and starts each line with pref -- We don't display the Empty tree treeshow pref Empty = "" -- Leaf treeshow pref (Node x Empty Empty) = (pshow pref x) -- Right branch is empty treeshow pref (Node x left Empty) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " left) -- Left branch is empty treeshow pref (Node x Empty right) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " right) -- Tree with left and right children non empty treeshow pref (Node x left right) = (pshow pref x) ++ "\n" ++ (showSon pref "|--" "| " left) ++ "\n" ++ (showSon pref "`--" " " right) -- shows a tree using some prefixes to make it nice showSon pref before next t = pref ++ before ++ treeshow (pref ++ next) t -- pshow replaces "\n" by "\n"++pref pshow pref x = replace '\n' ("\n"++pref) (show x) -- replaces one char by another string replace c new string = concatMap (change c new) string where change c new x | x == c = new | otherwise = x:[] -- "x" treeFromList :: (Ord a) => [a] -> BinTree a treeFromList [] = Empty treeFromList (x:xs) = Node x (treeFromList (filter (x) xs)) -- show main = do putStrLn "Int binary tree:" print $ treeFromList [7,2,4,8,1,3,6,21,12,23] -- /show ``` Now it is far better! The root is shown by starting the line with the `<` character. And each following line starts with a `:`. But we could also use another type. ``` active haskell data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Eq,Ord) -- declare BinTree a to be an instance of Show instance (Show a) => Show (BinTree a) where -- will start by a '<' before the root -- and put a : a begining of line show t = "< " ++ replace '\n' "\n: " (treeshow "" t) where -- treeshow pref Tree -- shows a tree and starts each line with pref -- We don't display the Empty tree treeshow pref Empty = "" -- Leaf treeshow pref (Node x Empty Empty) = (pshow pref x) -- Right branch is empty treeshow pref (Node x left Empty) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " left) -- Left branch is empty treeshow pref (Node x Empty right) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " right) -- Tree with left and right children non empty treeshow pref (Node x left right) = (pshow pref x) ++ "\n" ++ (showSon pref "|--" "| " left) ++ "\n" ++ (showSon pref "`--" " " right) -- shows a tree using some prefixes to make it nice showSon pref before next t = pref ++ before ++ treeshow (pref ++ next) t -- pshow replaces "\n" by "\n"++pref pshow pref x = replace '\n' ("\n"++pref) (show x) -- replaces one char by another string replace c new string = concatMap (change c new) string where change c new x | x == c = new | otherwise = x:[] -- "x" treeFromList :: (Ord a) => [a] -> BinTree a treeFromList [] = Empty treeFromList (x:xs) = Node x (treeFromList (filter (x) xs)) -- show main = do putStrLn "\nString binary tree:" print $ treeFromList ["foo","bar","baz","gor","yog"] -- /show ``` As we can test equality and order trees, we can make tree of trees! ```active haskell data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Eq,Ord) -- declare BinTree a to be an instance of Show instance (Show a) => Show (BinTree a) where -- will start by a '<' before the root -- and put a : a begining of line show t = "< " ++ replace '\n' "\n: " (treeshow "" t) where -- treeshow pref Tree -- shows a tree and starts each line with pref -- We don't display the Empty tree treeshow pref Empty = "" -- Leaf treeshow pref (Node x Empty Empty) = (pshow pref x) -- Right branch is empty treeshow pref (Node x left Empty) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " left) -- Left branch is empty treeshow pref (Node x Empty right) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " right) -- Tree with left and right children non empty treeshow pref (Node x left right) = (pshow pref x) ++ "\n" ++ (showSon pref "|--" "| " left) ++ "\n" ++ (showSon pref "`--" " " right) -- shows a tree using some prefixes to make it nice showSon pref before next t = pref ++ before ++ treeshow (pref ++ next) t -- pshow replaces "\n" by "\n"++pref pshow pref x = replace '\n' ("\n"++pref) (show x) -- replaces one char by another string replace c new string = concatMap (change c new) string where change c new x | x == c = new | otherwise = x:[] -- "x" treeFromList :: (Ord a) => [a] -> BinTree a treeFromList [] = Empty treeFromList (x:xs) = Node x (treeFromList (filter (x) xs)) -- show main = do putStrLn "\nBinary tree of Char binary trees:" print ( treeFromList (map treeFromList ["baz","zara","bar"])) -- /show ``` This is why I chose to prefix each line of tree display by `:` (except for the root). ![Yo Dawg Tree](http://yannesposito.com/Scratch/img/blog/Haskell-the-Hard-Way/yo_dawg_tree.jpg) ``` active haskell data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Eq,Ord) -- declare BinTree a to be an instance of Show instance (Show a) => Show (BinTree a) where -- will start by a '<' before the root -- and put a : a begining of line show t = "< " ++ replace '\n' "\n: " (treeshow "" t) where -- treeshow pref Tree -- shows a tree and starts each line with pref -- We don't display the Empty tree treeshow pref Empty = "" -- Leaf treeshow pref (Node x Empty Empty) = (pshow pref x) -- Right branch is empty treeshow pref (Node x left Empty) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " left) -- Left branch is empty treeshow pref (Node x Empty right) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " right) -- Tree with left and right children non empty treeshow pref (Node x left right) = (pshow pref x) ++ "\n" ++ (showSon pref "|--" "| " left) ++ "\n" ++ (showSon pref "`--" " " right) -- this shows a tree using some prefixes to make it nice showSon pref before next t = pref ++ before ++ treeshow (pref ++ next) t -- pshow replaces "\n" by "\n"++pref pshow pref x = replace '\n' ("\n"++pref) (show x) -- replaces one char by another string replace c new string = concatMap (change c new) string where change c new x | x == c = new | otherwise = x:[] -- "x" treeFromList :: (Ord a) => [a] -> BinTree a treeFromList [] = Empty treeFromList (x:xs) = Node x (treeFromList (filter (x) xs)) -- show main = do putStrLn "\nTree of Binary trees of Char binary trees:" print $ (treeFromList . map (treeFromList . map treeFromList)) [ ["YO","DAWG"] , ["I","HEARD"] , ["I","HEARD"] , ["YOU","LIKE","TREES"] ] -- /show ``` Which is equivalent to ``` haskell print ( treeFromList ( map treeFromList [ map treeFromList ["YO","DAWG"] , map treeFromList ["I","HEARD"] , map treeFromList ["I","HEARD"] , map treeFromList ["YOU","LIKE","TREES"] ])) ``` Notice how duplicate trees aren't inserted; there is only one tree corresponding to `"I","HEARD"`. We have this for (almost) free, because we have declared Tree to be an instance of `Eq`. See how awesome this structure is. We can make trees containing not only integers, strings and chars, but also other trees. And we can even make a tree containing a tree of trees! ### Infinite Structures ![Escher](http://yannesposito.com/Scratch/img/blog/Haskell-the-Hard-Way/escher_infinite_lizards.jpg) It is often stated that Haskell is _lazy_. In fact, if you are a bit pedantic, you should state that [Haskell is _non-strict_](http://www.haskell.org/haskellwiki/Lazy_vs._non-strict). Laziness is just a common implementation for non-strict languages. Then what does not-strict means? From the Haskell wiki: > Reduction (the mathematical term for evaluation) proceeds from the outside in. > > so if you have `(a+(b*c))` then you first reduce `+` first, then you reduce the inner `(b*c)` For example in Haskell you can do: ``` active haskell -- numbers = [0,1,2,..] numbers :: [Integer] numbers = 0:map (1+) numbers take' n [] = [] take' 0 l = [] take' n (x:xs) = x:take' (n-1) xs main = print $ take' 10 numbers ``` And it stops. How? Instead of trying to evaluate `numbers` entirely, it evaluates elements only when needed. Also, note in Haskell there is a notation for infinite lists ``` [1..] ⇔ [1,2,3,4...] [1,3..] ⇔ [1,3,5,7,9,11...] ``` And most functions will work with them. Also, there is a built-in function `take` which is equivalent to our `take'`. Suppose we don't mind having an ordered binary tree. Here is an infinite binary tree: ``` haskell nullTree = Node 0 nullTree nullTree ``` A complete binary tree where each node is equal to 0. Now I will prove you can manipulate this object using the following function: ``` haskell -- take all element of a BinTree -- up to some depth treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let nl = treeTakeDepth (n-1) left nr = treeTakeDepth (n-1) right in Node x nl nr ``` See what occurs for this program: ``` active haskell import Data.List data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Eq,Ord) -- declare BinTree a to be an instance of Show instance (Show a) => Show (BinTree a) where -- will start by a '<' before the root -- and put a : a begining of line show t = "< " ++ replace '\n' "\n: " (treeshow "" t) where treeshow pref Empty = "" treeshow pref (Node x Empty Empty) = (pshow pref x) treeshow pref (Node x left Empty) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " left) treeshow pref (Node x Empty right) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " right) treeshow pref (Node x left right) = (pshow pref x) ++ "\n" ++ (showSon pref "|--" "| " left) ++ "\n" ++ (showSon pref "`--" " " right) -- This shows a tree using some prefixes to make it nice showSon pref before next t = pref ++ before ++ treeshow (pref ++ next) t -- pshow replace "\n" by "\n"++pref pshow pref x = replace '\n' ("\n"++pref) (" " ++ show x) -- replace on char by another string replace c new string = concatMap (change c new) string where change c new x | x == c = new | otherwise = x:[] -- "x" nullTree = Node 0 nullTree nullTree -- take all element of a BinTree -- up to some depth treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let nl = treeTakeDepth (n-1) left nr = treeTakeDepth (n-1) right in Node x nl nr -- show main = print $ treeTakeDepth 4 nullTree -- /show ``` This code compiles, runs and stops. Just to heat up your neurones a bit more, let's make a slightly more interesting tree: ``` haskell iTree = Node 0 (dec iTree) (inc iTree) where dec (Node x l r) = Node (x-1) (dec l) (dec r) inc (Node x l r) = Node (x+1) (inc l) (inc r) ``` Another way to create this tree is to use a higher order function. This function should be similar to `map`, but should work on `BinTree` instead of list. Here is such a function: ``` haskell -- apply a function to each node of Tree treeMap :: (a -> b) -> BinTree a -> BinTree b treeMap f Empty = Empty treeMap f (Node x left right) = Node (f x) (treeMap f left) (treeMap f right) ``` _Hint_: I won't talk more about this here. If you are interested by the generalization of `map` to other data structures, search for functor and `fmap`. Our definition is now: ``` haskell infTreeTwo :: BinTree Int infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) (treeMap (\x -> x+1) infTreeTwo) ``` Look at the result for ``` active haskell import Data.List data BinTree a = Empty | Node a (BinTree a) (BinTree a) deriving (Eq,Ord) -- declare BinTree a to be an instance of Show instance (Show a) => Show (BinTree a) where -- will start by a '<' before the root -- and put a : a begining of line show t = "< " ++ replace '\n' "\n: " (treeshow "" t) where treeshow pref Empty = "" treeshow pref (Node x Empty Empty) = (pshow pref x) treeshow pref (Node x left Empty) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " left) treeshow pref (Node x Empty right) = (pshow pref x) ++ "\n" ++ (showSon pref "`--" " " right) treeshow pref (Node x left right) = (pshow pref x) ++ "\n" ++ (showSon pref "|--" "| " left) ++ "\n" ++ (showSon pref "`--" " " right) showSon pref before next t = pref ++ before ++ treeshow (pref ++ next) t -- pshow replace "\n" by "\n"++pref pshow pref x = replace '\n' ("\n"++pref) (" " ++ show x) -- replace on char by another string replace c new string = concatMap (change c new) string where change c new x | x == c = new | otherwise = x:[] -- "x" iTree = Node 0 (dec iTree) (inc iTree) where dec (Node x l r) = Node (x-1) (dec l) (dec r) inc (Node x l r) = Node (x+1) (inc l) (inc r) -- apply a function to each node of Tree treeMap :: (a -> b) -> BinTree a -> BinTree b treeMap f Empty = Empty treeMap f (Node x left right) = Node (f x) (treeMap f left) (treeMap f right) infTreeTwo :: BinTree Int infTreeTwo = Node 0 (treeMap (\x -> x-1) infTreeTwo) (treeMap (\x -> x+1) infTreeTwo) treeTakeDepth _ Empty = Empty treeTakeDepth 0 _ = Empty treeTakeDepth n (Node x left right) = let nl = treeTakeDepth (n-1) left nr = treeTakeDepth (n-1) right in Node x nl nr -- show main = print $ treeTakeDepth 4 infTreeTwo -- /show ``` [continue to next part](https://www.fpcomplete.com/school/haskell-fast-hard/haskell-fast-hard-part-5)