diff --git a/src/Chapter4.hs b/src/Chapter4.hs index 9fee476a..ce9325c1 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -114,22 +114,23 @@ As always, try to guess the output first! And don't forget to insert the output in here: >>> :k Char - +Char :: * >>> :k Bool - +Bool :: * >>> :k [Int] - +[Int] :: * >>> :k [] - +[] :: * -> * >>> :k (->) - +(->) :: * -> * -> * >>> :k Either - +Either :: * -> * -> * >>> data Trinity a b c = MkTrinity a b c >>> :k Trinity - +Trinity :: * -> * -> * -> * >>> data IntBox f = MkIntBox (f Int) >>> :k IntBox +IntBox :: (* -> *) -> * -} @@ -293,7 +294,8 @@ values and apply them to the type level? -} instance Functor (Secret e) where fmap :: (a -> b) -> Secret e a -> Secret e b - fmap = error "fmap for Box: not implemented!" + fmap _ (Trap e) = Trap e + fmap f (Reward a) = Reward (f a) {- | =⚔️= Task 3 @@ -307,6 +309,11 @@ data List a = Empty | Cons a (List a) +instance Functor List where + fmap :: (a -> b) -> List a -> List b + fmap _ Empty = Empty + fmap f (Cons x xs) = Cons (f x) (fmap f xs) + {- | =🛡= Applicative @@ -472,10 +479,11 @@ Implement the Applicative instance for our 'Secret' data type from before. -} instance Applicative (Secret e) where pure :: a -> Secret e a - pure = error "pure Secret: Not implemented!" + pure = Reward (<*>) :: Secret e (a -> b) -> Secret e a -> Secret e b - (<*>) = error "(<*>) Secret: Not implemented!" + Trap e <*> _ = Trap e + Reward f <*> x = fmap f x {- | =⚔️= Task 5 @@ -488,7 +496,18 @@ Implement the 'Applicative' instance for our 'List' type. may also need to implement a few useful helper functions for our List type. -} +instance Applicative List where + pure :: a -> List a + pure x = Cons x Empty + (<*>) :: List (a -> b) -> List a -> List b + Empty <*> _ = Empty + _ <*> Empty = Empty + Cons f fs <*> l = append (fmap f l) (fs <*> l) + +append :: List a -> List a -> List a +append Empty ys = ys +append (Cons x xs) ys = Cons x (append xs ys) {- | =🛡= Monad @@ -600,7 +619,8 @@ Implement the 'Monad' instance for our 'Secret' type. -} instance Monad (Secret e) where (>>=) :: Secret e a -> (a -> Secret e b) -> Secret e b - (>>=) = error "bind Secret: Not implemented!" + Trap e >>= _ = Trap e + Reward a >>= f = f a {- | =⚔️= Task 7 @@ -610,7 +630,13 @@ Implement the 'Monad' instance for our lists. 🕯 HINT: You probably will need to implement a helper function (or maybe a few) to flatten lists of lists to a single list. -} +instance Monad List where + (>>=) :: List a -> (a -> List b) -> List b + l >>= f = concatList (fmap f l) +concatList :: List (List a) -> List a +concatList Empty = Empty +concatList (Cons x xs) = append x (concatList xs) {- | =💣= Task 8*: Before the Final Boss @@ -629,7 +655,7 @@ Can you implement a monad version of AND, polymorphic over any monad? 🕯 HINT: Use "(>>=)", "pure" and anonymous function -} andM :: (Monad m) => m Bool -> m Bool -> m Bool -andM = error "andM: Not implemented!" +andM ma mb = ma >>= \a -> if a then mb else pure False {- | =🐉= Task 9*: Final Dungeon Boss @@ -672,7 +698,22 @@ Specifically, subtree of a tree ❃ Implement the function to convert Tree to list -} - +data Tree a + = Leaf + | Node a (Tree a) (Tree a) + +instance Functor Tree where + fmap :: (a -> b) -> Tree a -> Tree b + fmap _ Leaf = Leaf + fmap f (Node x l r) = Node (f x) (fmap f l) (fmap f r) + +reverseTree :: Tree a -> Tree a +reverseTree Leaf = Leaf +reverseTree (Node x l r) = Node x (reverseTree r) (reverseTree l) + +treeToList :: Tree a -> [a] +treeToList Leaf = [] +treeToList (Node x l r) = x : treeToList l ++ treeToList r {- You did it! Now it is time to the open pull request with your changes