From 6fc0a119217a602111cf9fe09b62d78d089c15f9 Mon Sep 17 00:00:00 2001 From: Phi Date: Thu, 14 Oct 2021 14:07:05 -0300 Subject: [PATCH 1/3] first chapter4 commit --- src/Chapter4.hs | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index a851c0b0..097f1cfb 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -42,6 +42,7 @@ Perfect. Let's crush this! module Chapter4 where + {- | =🛡= Kinds @@ -114,22 +115,30 @@ 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 :: (* -> *) -> * -} @@ -267,7 +276,8 @@ instance Functor Maybe where fmap _ x = x @ -} - +-- The type of x is a, and that implementation does not change the +-- type of a to b, so the return type is wrong {- | =⚔️= Task 2 @@ -282,7 +292,6 @@ data Secret e a | Reward a deriving (Show, Eq) - {- | Functor works with types that have kind `* -> *` but our 'Secret' has kind `* -> * -> *`. What should we do? Don't worry. We can partially @@ -293,7 +302,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 @@ -306,6 +316,12 @@ typeclasses for standard data types. data List a = Empty | Cons a (List a) + deriving Show + +instance Functor List where + fmap :: (a -> b) -> List a -> List b + fmap _ Empty = Empty + fmap f (Cons a l) = Cons (f a) (fmap f l) {- | =🛡= Applicative @@ -472,10 +488,12 @@ 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 = f <$> x + {- | =⚔️= Task 5 @@ -488,7 +506,19 @@ 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) <*> x = append' (f <$> x) (fs <*> x) + +append' :: List a -> List a -> List a +append' x Empty = x +append' Empty x = x +append' (Cons x xs) ys = Cons x (append' xs ys) {- | =🛡= Monad From abb150f3ef5e972e5ef5bb24ecf935dc68f3f3da Mon Sep 17 00:00:00 2001 From: Phi Date: Thu, 14 Oct 2021 14:51:44 -0300 Subject: [PATCH 2/3] everything done besides the last challenge --- src/Chapter4.hs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index 097f1cfb..e5525021 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -630,7 +630,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 r >>= f = f r {- | =⚔️= Task 7 @@ -641,6 +642,12 @@ Implement the 'Monad' instance for our lists. maybe a few) to flatten lists of lists to a single list. -} +instance Monad List where + (>>=) :: List a -> (a -> List b) -> List b + Empty >>= _ = Empty + (Cons x xs) >>= f = append' (f x) (xs >>= f) + + {- | =💣= Task 8*: Before the Final Boss @@ -658,8 +665,10 @@ Can you implement a monad version of AND, polymorphic over any monad? 🕯 HINT: Use "(>>=)", "pure" and anonymous function -} +-- weird expected behavior, I personally assumed it would be the same as +-- liftM2 (&&), but that was not the case andM :: (Monad m) => m Bool -> m Bool -> m Bool -andM = error "andM: Not implemented!" +andM b1 b2 = b1 >>= (\b -> if not b then pure b else (&&) b <$> b2) {- | =🐉= Task 9*: Final Dungeon Boss @@ -703,7 +712,14 @@ Specifically, ❃ Implement the function to convert Tree to list -} +data Tree a = Nil + | Node a (Tree a) (Tree a) + +instance Functor Tree where + fmap _ Nil = Nil + fmap f (Node x left right) = Node (f x) (fmap f left) (fmap f right) +reverseTree :: Tree a -> Tree a {- You did it! Now it is time to open pull request with your changes and summon @vrom911 and @chshersh for the review! From b0e2b4cfde7e4d64203c411146a9dc2b8ebb4533 Mon Sep 17 00:00:00 2001 From: Phi Date: Thu, 14 Oct 2021 15:29:43 -0300 Subject: [PATCH 3/3] finished! --- src/Chapter4.hs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index e5525021..43ad7baa 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -712,14 +712,24 @@ Specifically, ❃ Implement the function to convert Tree to list -} +-- this felt a little easy for a final boss xD + data Tree a = Nil | Node a (Tree a) (Tree a) + deriving Show instance Functor Tree where fmap _ Nil = Nil fmap f (Node x left right) = Node (f x) (fmap f left) (fmap f right) reverseTree :: Tree a -> Tree a +reverseTree Nil = Nil +reverseTree (Node x left right) = Node x (reverseTree right) (reverseTree left) + +treeToList :: Tree a -> [a] +treeToList Nil = [] +treeToList (Node x left right) = x : (treeToList left ++ treeToList right) + {- You did it! Now it is time to open pull request with your changes and summon @vrom911 and @chshersh for the review!