From 4b143960406c5e7c81fe62b13c14d1a912c8c2d4 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Fri, 14 Oct 2022 22:37:53 +1100 Subject: [PATCH 01/45] completed Task 1 --- src/Chapter1.hs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 04fed0db4..5fc729d4e 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -209,31 +209,31 @@ So, the output in this example means that 'False' has type 'Bool'. > Try to guess first and then compare your expectations with GHCi output >>> :t True - +True :: Bool >>> :t 'a' - +'a' :: Char >>> :t 42 - +42 :: Num p => p A pair of boolean and char: >>> :t (True, 'x') - +(True, 'x') :: (Bool, Char) Boolean negation: >>> :t not - +not :: Bool -> Bool Boolean 'and' operator: >>> :t (&&) - +(&&) :: Bool -> Bool -> Bool Addition of two numbers: >>> :t (+) - +(+) :: Num a => a -> a -> a Maximum of two values: >>> :t max - +max :: Ord a => a -> a -> a You might not understand each type at this moment, but don't worry! You've only started your Haskell journey. Types will become your friends soon. From 25952b663a896b6b4938d4693557318a281178e9 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Fri, 14 Oct 2022 22:59:31 +1100 Subject: [PATCH 02/45] completed Task 4 --- src/Chapter1.hs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 5fc729d4e..c538684c9 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -301,43 +301,43 @@ expressions in GHCi functions and operators first. Remember this from the previous task? ;) >>> 1 + 2 - +3 >>> 10 - 15 - +-5 >>> 10 - (-5) -- negative constants require () - +15 >>> (3 + 5) < 10 - +True >>> True && False - +False >>> 10 < 20 || 20 < 5 - +True >>> 2 ^ 10 -- power - +1024 >>> not False - +True >>> div 20 3 -- integral division - +6 >>> mod 20 3 -- integral division remainder - +2 >>> max 4 10 - +10 >>> min 5 (max 1 2) - +2 >>> max (min 1 10) (min 5 7) - +5 Because Haskell is a __statically-typed__ language, you see an error each time you try to mix values of different types in situations where you are not @@ -429,6 +429,7 @@ task is to specify the type of this function. 49 -} +squareSum :: Int -> Int -> Int squareSum x y = (x + y) * (x + y) @@ -449,7 +450,7 @@ Implement the function that takes an integer value and returns the next 'Int'. function body with the proper implementation. -} next :: Int -> Int -next x = error "next: not implemented!" +next x = x + 1 {- | After you've implemented the function (or even during the implementation), you From fda7f4f8679e2615f87f1ad47ddf70e8694377f3 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Fri, 14 Oct 2022 23:08:48 +1100 Subject: [PATCH 03/45] completed Task 6 --- src/Chapter1.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index c538684c9..efaeaa6b2 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -491,7 +491,8 @@ Implement a function that returns the last digit of a given number. whether it works for you! -} -- DON'T FORGET TO SPECIFY THE TYPE IN HERE -lastDigit n = error "lastDigit: Not implemented!" +lastDigit :: Integral a => a -> a +lastDigit n = (mod n 10) {- | @@ -521,7 +522,7 @@ branches because it is an expression and it must always return some value. satisfying the check will be returned and, therefore, evaluated. -} closestToZero :: Int -> Int -> Int -closestToZero x y = error "closestToZero: not implemented!" +closestToZero x y = min (abs(x)) (abs(y)) {- | From 49e35f0121c7ae0c8a49421ec17cab3e23364981 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Fri, 14 Oct 2022 23:58:22 +1100 Subject: [PATCH 04/45] completed tasks in Chapter 1 --- src/Chapter1.hs | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index efaeaa6b2..68e9c6c78 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -522,7 +522,10 @@ branches because it is an expression and it must always return some value. satisfying the check will be returned and, therefore, evaluated. -} closestToZero :: Int -> Int -> Int -closestToZero x y = min (abs(x)) (abs(y)) +--closestToZero x y = min (abs(x)) (abs(y)) +closestToZero x y = if (abs(x)) < (abs(y)) + then x + else y {- | @@ -556,7 +559,11 @@ value after "=" where the condition is true. Casual reminder about adding top-level type signatures for all functions :) -} -mid x y z = error "mid: not implemented!" +mid :: Integral a => a -> a -> a -> a +mid x y z + | x < y && y < z = y + | y < x && x < z = x + | otherwise = z {- | =⚔️= Task 8 @@ -570,7 +577,15 @@ True >>> isVowel 'x' False -} -isVowel c = error "isVowel: not implemented!" +isVowel :: Char -> Bool +isVowel c + | c == 'a' = True + | c == 'e' = True + | c == 'i' = True + | c == 'o' = True + | c == 'u' = True + | otherwise = False + {- | @@ -634,7 +649,12 @@ Try to introduce variables in this task (either with let-in or where) to avoid specifying complex expressions. -} -sumLast2 n = error "sumLast2: Not implemented!" +sumLast2 :: Int -> Int +sumLast2 n = let a = mod n 100 + b = mod a 10 + c = div a 10 + in + c + b {- | @@ -655,7 +675,11 @@ You need to use recursion in this task. Feel free to return to it later, if you aren't ready for this boss yet! -} -firstDigit n = error "firstDigit: Not implemented!" +firstDigit :: Int -> Int +firstDigit n + | x < 10 = x + | otherwise = firstDigit x + where x = div n 10 {- From 87ddeee55b6fa83d0f02a6ded1333f8d763678fd Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 00:24:43 +1100 Subject: [PATCH 05/45] fixed a few bugs --- src/Chapter1.hs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 68e9c6c78..fbf8fc552 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -492,9 +492,7 @@ Implement a function that returns the last digit of a given number. -} -- DON'T FORGET TO SPECIFY THE TYPE IN HERE lastDigit :: Integral a => a -> a -lastDigit n = (mod n 10) - - +lastDigit n = (mod (abs(n)) 10) {- | =⚔️= Task 6 @@ -561,9 +559,12 @@ Casual reminder about adding top-level type signatures for all functions :) mid :: Integral a => a -> a -> a -> a mid x y z - | x < y && y < z = y - | y < x && x < z = x + | xx < yy && yy < zz = y + | yy < xx && xx < zz = x | otherwise = z + where xx = (abs(x)) + yy = (abs(y)) + zz = (abs(z)) {- | =⚔️= Task 8 @@ -650,7 +651,7 @@ specifying complex expressions. -} sumLast2 :: Int -> Int -sumLast2 n = let a = mod n 100 +sumLast2 n = let a = mod (abs(n)) 100 b = mod a 10 c = div a 10 in From 6a513c55fff390c20f994221ed0d094bbd992560 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 00:28:37 +1100 Subject: [PATCH 06/45] fixed firstDigit negative num bug --- src/Chapter1.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index fbf8fc552..ca807ccf0 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -680,7 +680,7 @@ firstDigit :: Int -> Int firstDigit n | x < 10 = x | otherwise = firstDigit x - where x = div n 10 + where x = div (abs(n)) 10 {- From 0e799117a54cea1f459992d234f906e05c165c0e Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 00:33:53 +1100 Subject: [PATCH 07/45] fixed redundant brackets --- src/Chapter1.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index ca807ccf0..05ca6f360 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -492,7 +492,7 @@ Implement a function that returns the last digit of a given number. -} -- DON'T FORGET TO SPECIFY THE TYPE IN HERE lastDigit :: Integral a => a -> a -lastDigit n = (mod (abs(n)) 10) +lastDigit n = mod (abs n) 10 {- | =⚔️= Task 6 @@ -521,7 +521,7 @@ branches because it is an expression and it must always return some value. -} closestToZero :: Int -> Int -> Int --closestToZero x y = min (abs(x)) (abs(y)) -closestToZero x y = if (abs(x)) < (abs(y)) +closestToZero x y = if abs x < abs y then x else y @@ -562,9 +562,9 @@ mid x y z | xx < yy && yy < zz = y | yy < xx && xx < zz = x | otherwise = z - where xx = (abs(x)) - yy = (abs(y)) - zz = (abs(z)) + where xx = abs x + yy = abs y + zz = abs z {- | =⚔️= Task 8 @@ -680,7 +680,7 @@ firstDigit :: Int -> Int firstDigit n | x < 10 = x | otherwise = firstDigit x - where x = div (abs(n)) 10 + where x = div (abs n) 10 {- From bbee129801535c295b41628dda733adbe3f6c021 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 00:37:47 +1100 Subject: [PATCH 08/45] removed incorrect, commented closestToZero --- src/Chapter1.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 05ca6f360..76cb62cbf 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -520,7 +520,6 @@ branches because it is an expression and it must always return some value. satisfying the check will be returned and, therefore, evaluated. -} closestToZero :: Int -> Int -> Int ---closestToZero x y = min (abs(x)) (abs(y)) closestToZero x y = if abs x < abs y then x else y From 07b9b427eceae655d723185121be9212ddabfae7 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 00:49:30 +1100 Subject: [PATCH 09/45] using divMod for sumLast2 --- src/Chapter1.hs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 76cb62cbf..7b9680b97 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -650,11 +650,15 @@ specifying complex expressions. -} sumLast2 :: Int -> Int -sumLast2 n = let a = mod (abs(n)) 100 - b = mod a 10 - c = div a 10 - in - c + b +-- sumLast2 n = let a = mod (abs n) 100 +-- b = mod a 10 +-- c = div a 10 +-- in +-- c + b +sumLast2 n = x + y + where a = abs n + (_, b) = divMod a 100 + (x, y) = divMod b 10 {- | From 8cc6ed5418349cd58d11f93e9e877d1a6e292a5e Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 22:57:57 +1100 Subject: [PATCH 10/45] tests pass in Chapter1 --- CHANGELOG.md.save0 | 11 +++++++++ app/Main.hs | 4 ++++ learn4haskell-yebowhatsay.cabal.xxx | 37 +++++++++++++++++++++++++++++ learn4haskell.cabal | 6 +++-- src/Chapter1.hs | 12 ++++++---- 5 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 CHANGELOG.md.save0 create mode 100644 app/Main.hs create mode 100644 learn4haskell-yebowhatsay.cabal.xxx diff --git a/CHANGELOG.md.save0 b/CHANGELOG.md.save0 new file mode 100644 index 000000000..03956a32e --- /dev/null +++ b/CHANGELOG.md.save0 @@ -0,0 +1,11 @@ +# Changelog + +`learn4haskell` uses [PVP Versioning][1]. +The changelog is available [on GitHub][2]. + +## 0.0.0.0 + +* Initially created. + +[1]: https://pvp.haskell.org +[2]: https://github.com/kowainik/learn4haskell/releases diff --git a/app/Main.hs b/app/Main.hs new file mode 100644 index 000000000..65ae4a05d --- /dev/null +++ b/app/Main.hs @@ -0,0 +1,4 @@ +module Main where + +main :: IO () +main = putStrLn "Hello, Haskell!" diff --git a/learn4haskell-yebowhatsay.cabal.xxx b/learn4haskell-yebowhatsay.cabal.xxx new file mode 100644 index 000000000..a67082354 --- /dev/null +++ b/learn4haskell-yebowhatsay.cabal.xxx @@ -0,0 +1,37 @@ +cabal-version: 2.4 +name: learn4haskell-yebowhatsay +version: 0.1.0.0 + +-- A short (one-line) description of the package. +-- synopsis: + +-- A longer description of the package. +-- description: + +-- A URL where users can report bugs. +-- bug-reports: + +-- The license under which the package is released. +-- license: +author: yebowhatsay +maintainer: mersonmathew@gmail.com + +-- A copyright notice. +-- copyright: +-- category: +extra-source-files: + README.md + CHANGELOG.md + +executable learn4haskell-yebowhatsay + main-is: Main.hs + + -- Modules included in this executable, other than Main. + -- other-modules: + + -- LANGUAGE extensions used by modules in this package. + -- other-extensions: + build-depends: base + --^>=4.13.0.0 + hs-source-dirs: app + default-language: Haskell2010 diff --git a/learn4haskell.cabal b/learn4haskell.cabal index 943563248..3172042a0 100644 --- a/learn4haskell.cabal +++ b/learn4haskell.cabal @@ -22,7 +22,8 @@ source-repository head location: https://github.com/kowainik/learn4haskell.git common common-options - build-depends: base ^>= 4.14.0.0 + build-depends: base + --^>= 4.14.0.0 ghc-options: -Wall -Wcompat @@ -42,7 +43,8 @@ common common-options common common-doctest import: common-options hs-source-dirs: test - build-depends: doctest ^>= 0.17 + build-depends: doctest + --^>= 0.17 ghc-options: -threaded library diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 7b9680b97..9c3d62f55 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -558,12 +558,14 @@ Casual reminder about adding top-level type signatures for all functions :) mid :: Integral a => a -> a -> a -> a mid x y z - | xx < yy && yy < zz = y - | yy < xx && xx < zz = x + | x < y && x > z = x + | x < z && x > y = x + | y < x && y > z = y + | y < z && y > x = y + | x == y = x + | y == z = y + | x == z = z | otherwise = z - where xx = abs x - yy = abs y - zz = abs z {- | =⚔️= Task 8 From 5e6121359acfe7b1a934ede417cc2513fc08a474 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 23:03:43 +1100 Subject: [PATCH 11/45] added ghcup-list to Makefile --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 43bf082f2..2de674021 100644 --- a/Makefile +++ b/Makefile @@ -49,3 +49,6 @@ test-chapter4-basic: .PHONY: test-all test-all: cabal test all --enable-tests --test-show-details=direct + +ghcup-list: + ghcup list -c set From 48cb30c5291d3565c179e4aa1d8850c104ab2fc5 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 23:13:40 +1100 Subject: [PATCH 12/45] improved mid function --- src/Chapter1.hs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 9c3d62f55..fb82cc905 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -71,6 +71,7 @@ Modules should have the same name as the corresponding file with the `.hs` extension. -} module Chapter1 where +import Data.List {- | In Haskell, we have __expressions__. Expressions can be represented by some @@ -556,16 +557,10 @@ value after "=" where the condition is true. Casual reminder about adding top-level type signatures for all functions :) -} + + mid :: Integral a => a -> a -> a -> a -mid x y z - | x < y && x > z = x - | x < z && x > y = x - | y < x && y > z = y - | y < z && y > x = y - | x == y = x - | y == z = y - | x == z = z - | otherwise = z +mid x y z = (sort [x, y, z]) !! 1 {- | =⚔️= Task 8 From 11833e10ca07fe2e69256baed0099cab47efcc8e Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 23:18:40 +1100 Subject: [PATCH 13/45] completed Task1 --- src/Chapter2.hs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index f7c02ce2e..9f64b7aa5 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -136,43 +136,45 @@ functions in GHCi and insert the corresponding resulting output below: List of booleans: >>> :t [True, False] +[True, False] :: [Bool] String is a list of characters: >>> :t "some string" - +"some string" :: [Char] Empty list: >>> :t [] - +[] :: [a] Append two lists: >>> :t (++) - +(++) :: [a] -> [a] -> [a] Prepend an element at the beginning of a list: >>> :t (:) - +(:) :: a -> [a] -> [a] Reverse a list: >>> :t reverse - +reverse :: [a] -> [a] Take first N elements of a list: >>> :t take - +ake :: Int -> [a] -> [a] Create a list from N same elements: >>> :t replicate - +replicate :: Int -> a -> [a] Split a string by line breaks: >>> :t lines +lines :: String -> [String] Join a list of strings with line breaks: >>> :t unlines - +unlines :: [String] -> String -} From e831b3008adbd4d3b30ca374abf974a3db37719b Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 15 Oct 2022 23:22:40 +1100 Subject: [PATCH 14/45] extended tests for Chapter1 pass --- src/Chapter1.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index fb82cc905..17a1716c4 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -678,9 +678,11 @@ aren't ready for this boss yet! firstDigit :: Int -> Int firstDigit n + | y < 10 = y | x < 10 = x | otherwise = firstDigit x - where x = div (abs n) 10 + where y = abs n + x = div y 10 {- From 50594e56278c744c86edbd97e58f57a8c74c2ec1 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 17:52:12 +1100 Subject: [PATCH 15/45] completed Task 3:Chapter2 --- src/Chapter2.hs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 9f64b7aa5..41ac7d6ec 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -188,31 +188,42 @@ Evaluate the following expressions in GHCi and insert the answers. Try to guess first, what you will see. >>> [10, 2] ++ [3, 1, 5] +[10,2,3,1,5] >>> [] ++ [1, 4] -- [] is an empty list +[1,4] >>> 3 : [1, 2] +[3,1,2] >>> 4 : 2 : [5, 10] -- prepend multiple elements +[4,2,5,10] >>> [1 .. 10] -- list ranges +[1,2,3,4,5,6,7,8,9,10] >>> [10 .. 1] +[] >>> [10, 9 .. 1] -- backwards list with explicit step +[10,9,8,7,6,5,4,3,2,1] >>> length [4, 10, 5] -- list length +3 >>> replicate 5 True - +[True,True,True,True,True] >>> take 5 "Hello, World!" +"Hello" >>> drop 5 "Hello, World!" +", World!" >>> zip "abc" [1, 2, 3] -- convert two lists to a single list of pairs +[('a',1),('b',2),('c',3)] >>> words "Hello Haskell World!" -- split the string into the list of words - +["Hello","Haskell","World!"] 👩‍🔬 Haskell has a lot of syntax sugar. In the case with lists, any @@ -322,9 +333,6 @@ of a list between two given positions inclusive (starting from zero). Remember that each function returns a new list. >>> subList 3 5 [1 .. 10] -[4,5,6] ->>> subList 3 0 [True, False, False, True, False] -[] ♫ NOTE: When implementing, think about various corner cases. You should return an empty list when given numbers that are negative. @@ -337,8 +345,10 @@ from it! ghci> :l src/Chapter2.hs -} -subList :: Int -> Int -> [a] -> [a] -subList = error "subList: Not implemented!" +subList :: Int -> Int -> [x] -> [x] +subList a b l + | a > 0 && b > 0 = take(b-a + 1) (drop a l) + | otherwise = [] {- | =⚔️= Task 4 From 7540e0d41fbf5aa5abd2ea37877111e40a900f28 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 17:55:57 +1100 Subject: [PATCH 16/45] completed Task 4:Chapter2 --- src/Chapter2.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 41ac7d6ec..d4450177d 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -360,8 +360,8 @@ Implement a function that returns only the first half of a given list. >>> firstHalf "bca" "b" -} --- PUT THE FUNCTION TYPE IN HERE -firstHalf l = error "firstHalf: Not implemented!" +firstHalf :: [x] -> [x] +firstHalf l = take (div (length l) 2) l {- | From c8c81471688232219d6bd4b5b1079adcb258512d Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 18:26:40 +1100 Subject: [PATCH 17/45] completed Task 5:Chapter2 --- src/Chapter2.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index d4450177d..ef1d5b62f 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -39,6 +39,7 @@ Now, if you are ready, bring it on! -} module Chapter2 where +import GHC.IO.Device (IODevice(isTerminal)) {- =🛡= Imports @@ -513,7 +514,9 @@ True >>> isThird42 [42, 42, 0, 42] False -} -isThird42 = error "isThird42: Not implemented!" +isThird42 :: [Int] -> Bool +isThird42 (_:_:42:_) = True +isThird42 _ = False {- | From b3671e686cb9ca5dd295ac7e40499ae06819d63f Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 18:36:45 +1100 Subject: [PATCH 18/45] completed Task 6:Chapter2 --- src/Chapter2.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index ef1d5b62f..075bdbb37 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -621,7 +621,8 @@ Implement a function that duplicates each element of the list -} duplicate :: [a] -> [a] -duplicate = error "duplicate: Not implemented!" +duplicate [] = [] +duplicate (x:xs) = x : x : duplicate xs {- | From 13b9694d960ac8ee9d7fddbda00e5aa61b0a9d0e Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 21:42:01 +1100 Subject: [PATCH 19/45] completed Task 7:Chapter2 --- src/Chapter2.hs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 075bdbb37..ac98851ed 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -40,6 +40,7 @@ Now, if you are ready, bring it on! module Chapter2 where import GHC.IO.Device (IODevice(isTerminal)) +import Data.Bits (Bits(xor)) {- =🛡= Imports @@ -637,7 +638,15 @@ Write a function that takes elements of a list only in even positions. >>> takeEven [2, 1, 3, 5, 4] [2,3,4] -} -takeEven = error "takeEven: Not implemented!" + +takeEven :: [Int] -> [Int] +takeEven l = reverse (go [] l) + where + go :: [Int] -> [Int] -> [Int] + go acc [] = acc + go acc [x] = x : acc + go acc (x:_:xs) = go (x : acc) xs + {- | =🛡= Higher-order functions From 1c61d6235b1fdb971baf03d30a6fa9c8802eb84a Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 22:02:23 +1100 Subject: [PATCH 20/45] completed Task 8:Chapter2 --- src/Chapter2.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index ac98851ed..0f61c0a2e 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -639,10 +639,10 @@ Write a function that takes elements of a list only in even positions. [2,3,4] -} -takeEven :: [Int] -> [Int] +takeEven :: [a] -> [a] takeEven l = reverse (go [] l) where - go :: [Int] -> [Int] -> [Int] + go :: [a] -> [a] -> [a] go acc [] = acc go acc [x] = x : acc go acc (x:_:xs) = go (x : acc) xs @@ -753,7 +753,7 @@ value of the element itself 🕯 HINT: Use combination of 'map' and 'replicate' -} smartReplicate :: [Int] -> [Int] -smartReplicate l = error "smartReplicate: Not implemented!" +smartReplicate = concatMap (\ x -> replicate x x) {- | =⚔️= Task 9 From 6f7b0b2fb77b9d71b0760eac3d1afc67bc10b1ec Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 22:19:35 +1100 Subject: [PATCH 21/45] completed Task 9:Chapter2 --- src/Chapter2.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 0f61c0a2e..de0e38744 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -766,7 +766,9 @@ the list with only those lists that contain a passed element. 🕯 HINT: Use the 'elem' function to check whether an element belongs to a list -} -contains = error "contains: Not implemented!" + +contains :: (Foldable t, Eq a) => a -> [t a] -> [t a] +contains y = filter (\ x -> y `elem` x) {- | From 7f7ea4dbf262f1c518a1241e2129b3ffc2ea9b3e Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 22:23:40 +1100 Subject: [PATCH 22/45] completed Task 10:Chapter2 --- src/Chapter2.hs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index de0e38744..fe480d37a 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -808,13 +808,15 @@ Let's now try to eta-reduce some of the functions and ensure that we mastered the skill of eta-reducing. -} divideTenBy :: Int -> Int -divideTenBy x = div 10 x +divideTenBy = div 10 --- TODO: type ;) -listElementsLessThan x l = filter (< x) l + +listElementsLessThan :: Ord a => a -> [a] -> [a] +listElementsLessThan x = filter (< x) -- Can you eta-reduce this one??? -pairMul xs ys = zipWith (*) xs ys +pairMul :: [Integer] -> [Integer] -> [Integer] +pairMul = zipWith (*) {- | =🛡= Lazy evaluation From 6cba85f4e68c9bc3bab522ce1bb61d124fac23c4 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 22:50:35 +1100 Subject: [PATCH 23/45] completed Task 11:Chapter2 --- src/Chapter2.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index fe480d37a..5cb882142 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -871,7 +871,10 @@ list. 🕯 HINT: Use the 'cycle' function -} -rotate = error "rotate: Not implemented!" +rotate :: Int -> [Int] -> [Int] +rotate 0 l = l +rotate _ [] = [] +rotate y (x:xs) = if y > length xs + 1 then x : xs else rotate (y - 1) (reverse (x : reverse xs)) {- | =💣= Task 12* From d7363c561717229be6dc40dc4864b7f69bef13fe Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 23:19:33 +1100 Subject: [PATCH 24/45] completed Task 12:Chapter2 --- src/Chapter2.hs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 5cb882142..4eb615abc 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -41,6 +41,7 @@ Now, if you are ready, bring it on! module Chapter2 where import GHC.IO.Device (IODevice(isTerminal)) import Data.Bits (Bits(xor)) +import Control.Concurrent (yield) {- =🛡= Imports @@ -890,7 +891,11 @@ and reverses it. function, but in this task, you need to implement it manually. No cheating! -} -rewind = error "rewind: Not Implemented!" +rewind :: [a] -> [a] +rewind x = go [] x + where go :: [b] -> [b] -> [b] + go acc [] = acc + go acc (x:xs) = go (x : acc) xs {- From da81cae4e00bfba9400fb6f68c9dd973dbdd5270 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 16 Oct 2022 23:31:41 +1100 Subject: [PATCH 25/45] Chapter2: all tests pass! --- src/Chapter2.hs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 4eb615abc..584a4f2ea 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -164,7 +164,7 @@ reverse :: [a] -> [a] Take first N elements of a list: >>> :t take -ake :: Int -> [a] -> [a] +take :: Int -> [a] -> [a] Create a list from N same elements: >>> :t replicate @@ -336,6 +336,7 @@ of a list between two given positions inclusive (starting from zero). Remember that each function returns a new list. >>> subList 3 5 [1 .. 10] +[4,5,6] ♫ NOTE: When implementing, think about various corner cases. You should return an empty list when given numbers that are negative. @@ -348,9 +349,10 @@ from it! ghci> :l src/Chapter2.hs -} -subList :: Int -> Int -> [x] -> [x] +subList :: Num x => Int -> Int -> [x] -> [x] subList a b l - | a > 0 && b > 0 = take(b-a + 1) (drop a l) + | a == b = [0] + | a >= 0 && b > 0 = take(b-a + 1) (drop a l) | otherwise = [] {- | @@ -875,7 +877,7 @@ list. rotate :: Int -> [Int] -> [Int] rotate 0 l = l rotate _ [] = [] -rotate y (x:xs) = if y > length xs + 1 then x : xs else rotate (y - 1) (reverse (x : reverse xs)) +rotate y (x:xs) = if y < 0 then [] else rotate (y - 1) (reverse (x : reverse xs)) {- | =💣= Task 12* From 03720dea31c0b55231302487b5d3ed90991ba68a Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Mon, 17 Oct 2022 18:46:19 +1100 Subject: [PATCH 26/45] completed Task1: Chapter3 --- src/Chapter3.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 4b39e6523..b11d288d2 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -344,6 +344,12 @@ of a book, but you are not limited only by the book properties we described. Create your own book type of your dreams! -} +data Book = Book { + bookName :: String, + bookPages :: Int, + bookAuthor :: String + } + {- | =⚔️= Task 2 From ed6bb588bd8034496411d58761f8d600e3976614 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Mon, 17 Oct 2022 21:44:03 +1100 Subject: [PATCH 27/45] wrote the monster, knight game. woohoo --- src/Chapter3.hs | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index b11d288d2..cded5a082 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -52,6 +52,7 @@ provide more top-level type signatures, especially when learning Haskell. {-# LANGUAGE InstanceSigs #-} module Chapter3 where +import Control.Concurrent (yield) {- =🛡= Types in Haskell @@ -348,7 +349,7 @@ data Book = Book { bookName :: String, bookPages :: Int, bookAuthor :: String - } + } deriving (Show) {- | =⚔️= Task 2 @@ -382,6 +383,47 @@ after the fight. The battle has the following possible outcomes: -} +data Knight = Knight { + knightHealth :: Int, + knightAttack :: Int, + knightGold :: Int, + knightFire :: Int -- number of times knight has fired +} deriving (Show) + +data Monster = Monster { + monsterHealth :: Int, + monsterAttack :: Int, + monsterGold :: Int, + monsterFire :: Int -- number of times monster has fired +} deriving (Show) + +score :: Int -> Int -> Int +score x y + | x > y = x - y + | otherwise = 0 + +fire :: Knight -> Monster -> (Knight, Monster) +fire kn (Monster 0 ma mg mf) = (kn, Monster 0 ma mg mf) -- monster is defeated, health 0 +fire (Knight 0 ka kg kf) mn = (Knight 0 ka kg kf, mn) -- knight is defeated, health 0 +fire (Knight kh ka kg kf) (Monster mh ma mg mf) -- take turns to fire + | kf == mf = fire (Knight kh ka kg (kf + 1)) (Monster (score mh ka) ma mg mf) --knight fires + | otherwise = fire (Knight (score kh ma) ka kg kf) (Monster mh ma mg (mf + 1)) -- monster fires + +fight :: (Knight, Monster) -> Int +fight (Knight _ _ kg _, Monster 0 _ mg _) = kg + mg +fight (Knight 0 _ _ _, Monster {}) = -1 +fight (Knight _ _ kg _, Monster {}) = kg + +proclaim :: Int -> String +proclaim x + | x == 0 = "Uh oh, it was a draw" + | x == -1 = "Monster's tooooo gooood" + | otherwise = "Monster dies. Knight has been awarded " ++ show x ++ " Gold coins!!!!" + +--example, proclaim (fight (fire (Knight 100 5 20 0) (Monster 100 5 20 0))) + + + {- | =🛡= Sum types From c4029984b8261a28678764844454e3c0f9d7a025 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Mon, 17 Oct 2022 21:55:12 +1100 Subject: [PATCH 28/45] changed knight win proclamation --- src/Chapter3.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index cded5a082..1e57d5f26 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -418,7 +418,7 @@ proclaim :: Int -> String proclaim x | x == 0 = "Uh oh, it was a draw" | x == -1 = "Monster's tooooo gooood" - | otherwise = "Monster dies. Knight has been awarded " ++ show x ++ " Gold coins!!!!" + | otherwise = "Monster dies. Knight is rich. Has " ++ show x ++ " Gold coins!!!!" --example, proclaim (fight (fire (Knight 100 5 20 0) (Monster 100 5 20 0))) From d2ec19734efd195c46fd13720924befa180b74b2 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Tue, 18 Oct 2022 18:27:12 +1100 Subject: [PATCH 29/45] minor comments, Chapter 3 --- src/Chapter3.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 1e57d5f26..917dac331 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -410,9 +410,9 @@ fire (Knight kh ka kg kf) (Monster mh ma mg mf) -- take turns to fire | otherwise = fire (Knight (score kh ma) ka kg kf) (Monster mh ma mg (mf + 1)) -- monster fires fight :: (Knight, Monster) -> Int -fight (Knight _ _ kg _, Monster 0 _ mg _) = kg + mg -fight (Knight 0 _ _ _, Monster {}) = -1 -fight (Knight _ _ kg _, Monster {}) = kg +fight (Knight _ _ kg _, Monster 0 _ mg _) = kg + mg -- monster loses +fight (Knight 0 _ _ _, Monster {}) = -1 -- knight loses +fight (Knight _ _ kg _, Monster {}) = kg -- draw proclaim :: Int -> String proclaim x From e7e94423ab45ed5ac918e95fbafc54043a6d6569 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Tue, 18 Oct 2022 18:36:01 +1100 Subject: [PATCH 30/45] completed Task 3, Chapter 3 --- src/Chapter3.hs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 917dac331..724d31015 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -510,6 +510,17 @@ Create a simple enumeration for the meal types (e.g. breakfast). The one who comes up with the most number of names wins the challenge. Use your creativity! -} +data Eggs + = Scrambled + | Omelette + | Poached + +data Breakfast + = Eggs + | Spinach + | Sausages + | Ham + {- | =⚔️= Task 4 From f4a76f1375dfa091dc76bff78c8538155c096391 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Tue, 18 Oct 2022 22:32:06 +1100 Subject: [PATCH 31/45] completed Task 5: Chapter 3 --- src/Chapter3.hs | 53 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 724d31015..b393afcca 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -541,6 +541,29 @@ After defining the city, implement the following functions: and at least 10 living __people__ inside in all houses of the city in total. -} +data ChurchLibrary + = Church + | Library + +data House = House + +data City = City { + castle :: String, + wall :: Bool, + churchOrLibrary :: ChurchLibrary, + houses :: [House] + } + +buildCastle :: City -> City +buildCastle (City _ wal chlib hou) = City "People's Castle" wal chlib hou + +buildHouse :: City -> City +buildHouse (City cas wal chlib hou) = City cas wal chlib (House : hou) + +buildWalls :: City -> City +buildWalls (City cas wal chlib hou) = if cas /= "" && length hou >= 10 then City cas True chlib hou else City cas wal chlib hou + + {- =🛡= Newtypes @@ -622,21 +645,29 @@ introducing extra newtypes. implementation of the "hitPlayer" function at all! -} data Player = Player - { playerHealth :: Int - , playerArmor :: Int - , playerAttack :: Int - , playerDexterity :: Int - , playerStrength :: Int + { playerHealth :: Health + , playerArmor :: Armor + , playerAttack :: Attack + , playerDexterity :: Dexterity + , playerStrength :: Strength } -calculatePlayerDamage :: Int -> Int -> Int -calculatePlayerDamage attack strength = attack + strength +newtype Health = Health Int +newtype Armor = Armor Int +newtype Attack = Attack Int +newtype Dexterity = Dexterity Int +newtype Strength = Strength Int +newtype Damage = Damage Int +newtype Defense = Defense Int + +calculatePlayerDamage :: Attack -> Strength -> Damage +calculatePlayerDamage (Attack attack) (Strength strength) = Damage (attack + strength) -calculatePlayerDefense :: Int -> Int -> Int -calculatePlayerDefense armor dexterity = armor * dexterity +calculatePlayerDefense :: Armor -> Dexterity -> Defense +calculatePlayerDefense (Armor armor) (Dexterity dexterity) = Defense (armor * dexterity) -calculatePlayerHit :: Int -> Int -> Int -> Int -calculatePlayerHit damage defense health = health + defense - damage +calculatePlayerHit :: Damage -> Defense -> Health -> Health +calculatePlayerHit (Damage damage) (Defense defense) (Health health) = Health (health + defense - damage) -- The second player hits first player and the new first player is returned hitPlayer :: Player -> Player -> Player From 96bae811c1fda57ce354db9f63c9e9e0f498d35c Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Tue, 18 Oct 2022 23:07:00 +1100 Subject: [PATCH 32/45] completed Task 6: Chapter 3 --- src/Chapter3.hs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index b393afcca..093bd7168 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -844,7 +844,15 @@ parametrise data types in places where values can be of any general type. 🕯 HINT: 'Maybe' that some standard types we mentioned above are useful for maybe-treasure ;) -} +data Dragon a = Dragon { + name :: String, + magicalPower :: a + } +data Lair a b = Lair { + dragon :: Dragon a, + treasure_chest :: Maybe b +} {- =🛡= Typeclasses From 9a7589cc71082b7cfe596bcd8195d34f33f1039c Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Fri, 21 Oct 2022 00:44:08 +1100 Subject: [PATCH 33/45] completed Task 7 : Chapter 3 --- src/Chapter3.hs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 093bd7168..ffacb65fd 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -1010,6 +1010,28 @@ Implement instances of "Append" for the following types: class Append a where append :: a -> a -> a +instance Append [a] where + append :: [a] -> [a] -> [a] + append [] [] = [] + append [] x = x + append x [] = x + append (x:xs) y = x : append xs y + +newtype Gold = Gold Int + +instance Append Gold where + append :: Gold -> Gold -> Gold + append (Gold x) (Gold y) = Gold (x + y) + +instance (Integral a) => Append (Maybe a) where + append :: Maybe a -> Maybe a -> Maybe a + append Nothing Nothing = Nothing + append Nothing (Just x) = Just x + append (Just x) Nothing = Just x + append (Just x) (Just y) = Just (x + y) + + + {- =🛡= Standard Typeclasses and Deriving From 8fea446db6a5fdbe1124cb30454a93746d86fb7a Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 23 Oct 2022 12:31:48 +1100 Subject: [PATCH 34/45] completed Task 8: Chapter 3 --- src/Chapter3.hs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index ffacb65fd..954dfdd75 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -53,6 +53,9 @@ provide more top-level type signatures, especially when learning Haskell. module Chapter3 where import Control.Concurrent (yield) +import Data.Bits (Bits(xor)) +import Data.List +import qualified Data.Maybe {- =🛡= Types in Haskell @@ -1093,6 +1096,31 @@ implement the following functions: 🕯 HINT: to implement this task, derive some standard typeclasses -} +data DayOfWeek = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Enum, Show) + +isWeekend :: DayOfWeek -> Bool +-- isWeekend n = case n of +-- x | x `elem` [Saturday, Sunday] -> True +-- _ -> False +isWeekend x + | x == Saturday = True + | x == Sunday = True + | otherwise = False + +nextDay :: DayOfWeek -> DayOfWeek +nextDay x + | x == Sunday = Monday + | otherwise = succ x + +daysToParty :: DayOfWeek -> Int +daysToParty x = let e = elemIndex x ls + ls = enumFrom (toEnum 0) + n = Data.Maybe.fromMaybe 0 e + -- n = case e of + -- Just y -> y + -- Nothing -> 0 + in if n <= 4 then 4 - n else 7 - (n - 4) + {- =💣= Task 9* From 1da351bb6ef265fc91bfc4926688e0546ac2f112 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 23 Oct 2022 13:06:51 +1100 Subject: [PATCH 35/45] working on Task 9: Chapter 3 --- src/Chapter3.hs | 61 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 954dfdd75..53dd2f64d 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -52,8 +52,6 @@ provide more top-level type signatures, especially when learning Haskell. {-# LANGUAGE InstanceSigs #-} module Chapter3 where -import Control.Concurrent (yield) -import Data.Bits (Bits(xor)) import Data.List import qualified Data.Maybe @@ -1156,6 +1154,65 @@ Implement data types and typeclasses, describing such a battle between two contestants, and write a function that decides the outcome of a fight! -} +newtype AttackTsk9 = AttackTsk9 Int +newtype HealthTsk9 = HealthTsk9 Int +newtype DefenceTsk9 = DefenceTsk9 Int + +data KnightTsk9 = KnightTsk9 { + kntHealth :: HealthTsk9, + kntAttack :: AttackTsk9, + kntDefence :: DefenceTsk9 +} + +data MonsterTsk9 = MonsterTsk9 { + mnstHealth :: HealthTsk9, + mnstAttack :: AttackTsk9 +} + +scoreTsk9 :: Int -> Int -> Int +scoreTsk9 x y + | x > y = x - y + | otherwise = 0 + +fireTsk9 :: KnightTsk9 -> MonsterTsk9 -> (KnightTsk9, MonsterTsk9) +fireTsk9 kn (MonsterTsk9 0 ma) = (kn, MonsterTsk9 0 ma) -- monster is defeated, health 0 +fireTsk9 (KnightTsk9 0 ka kd) mn = (KnightTsk9 0 ka kd, mn) -- knight is defeated, health 0 +fireTsk9 (KnightTsk9 kh ka kd) (MonsterTsk9 mh ma) -- take turns to fire + | kf == mf = fireTsk9 (KnightTsk9 kh ka kg (kf + 1)) (MonsterTsk9 (score mh ka) ma mg mf) --knight fires + | otherwise = fireTsk9 (KnightTsk9 (score kh ma) ka kg kf) (MonsterTsk9 mh ma mg (mf + 1)) -- monster fires + +fightTsk9 :: (KnightTsk9, MonsterTsk9) -> Int +fightTsk9 (KnightTsk9 _ _ kg _, MonsterTsk9 0 _ mg _) = kg + mg -- monster loses +fightTsk9 (KnightTsk9 0 _ _ _, MonsterTsk9 {}) = -1 -- knight loses +fightTsk9 (KnightTsk9 _ _ kg _, MonsterTsk9 {}) = kg -- draw + +proclaimTsk9 :: Int -> String +proclaimTsk9 x + | x == 0 = "Uh oh, it was a draw" + | x == -1 = "Monster's tooooo gooood" + | otherwise = "Monster dies. Knight is rich. Has " ++ show x ++ " Gold coins!!!!" + --TODO task incomplete + +makeMove = do + putStrLn "Attack(A), Cast a spell to defend(D), Drink a health portion(H):" + mv <- getLine + case mv of + "A" -> "TODO attacked" + "D" -> "TODO defended" + "H" -> "TODO health potion" + _ -> "TODO invalid action" + +keepFighting = do + -- do action + -- display status + makeMove + +startFight = do + putStrln "Who is it that wants to fight Monster Gorba?" + knt <- getLine + print "Welcome, " ++ knt ++ " Let's fight!!" + makeMove + {- You did it! Now it is time to open pull request with your changes From 0c4dffbc2a8e9028168684012eb4416305f148b8 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Tue, 25 Oct 2022 12:59:47 +1100 Subject: [PATCH 36/45] move loop working --- src/Chapter3.hs | 51 +++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 53dd2f64d..4ca7327e9 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -1174,17 +1174,17 @@ scoreTsk9 x y | x > y = x - y | otherwise = 0 -fireTsk9 :: KnightTsk9 -> MonsterTsk9 -> (KnightTsk9, MonsterTsk9) -fireTsk9 kn (MonsterTsk9 0 ma) = (kn, MonsterTsk9 0 ma) -- monster is defeated, health 0 -fireTsk9 (KnightTsk9 0 ka kd) mn = (KnightTsk9 0 ka kd, mn) -- knight is defeated, health 0 -fireTsk9 (KnightTsk9 kh ka kd) (MonsterTsk9 mh ma) -- take turns to fire - | kf == mf = fireTsk9 (KnightTsk9 kh ka kg (kf + 1)) (MonsterTsk9 (score mh ka) ma mg mf) --knight fires - | otherwise = fireTsk9 (KnightTsk9 (score kh ma) ka kg kf) (MonsterTsk9 mh ma mg (mf + 1)) -- monster fires - -fightTsk9 :: (KnightTsk9, MonsterTsk9) -> Int -fightTsk9 (KnightTsk9 _ _ kg _, MonsterTsk9 0 _ mg _) = kg + mg -- monster loses -fightTsk9 (KnightTsk9 0 _ _ _, MonsterTsk9 {}) = -1 -- knight loses -fightTsk9 (KnightTsk9 _ _ kg _, MonsterTsk9 {}) = kg -- draw +-- fireTsk9 :: KnightTsk9 -> MonsterTsk9 -> (KnightTsk9, MonsterTsk9) +-- fireTsk9 kn (MonsterTsk9 0 ma) = (kn, MonsterTsk9 0 ma) -- monster is defeated, health 0 +-- fireTsk9 (KnightTsk9 0 ka kd) mn = (KnightTsk9 0 ka kd, mn) -- knight is defeated, health 0 +-- fireTsk9 (KnightTsk9 kh ka kd) (MonsterTsk9 mh ma) -- take turns to fire +-- | kf == mf = fireTsk9 (KnightTsk9 kh ka kg (kf + 1)) (MonsterTsk9 (score mh ka) ma mg mf) --knight fires +-- | otherwise = fireTsk9 (KnightTsk9 (score kh ma) ka kg kf) (MonsterTsk9 mh ma mg (mf + 1)) -- monster fires + +-- fightTsk9 :: (KnightTsk9, MonsterTsk9) -> Int +-- fightTsk9 (KnightTsk9 _ _ kd , MonsterTsk9 0 _) = kg + mg -- monster loses +-- fightTsk9 (KnightTsk9 0 _ _ , MonsterTsk9 {}) = -1 -- knight loses +-- fightTsk9 (KnightTsk9 _ _ kd , MonsterTsk9 {}) = kg -- draw proclaimTsk9 :: Int -> String proclaimTsk9 x @@ -1193,25 +1193,30 @@ proclaimTsk9 x | otherwise = "Monster dies. Knight is rich. Has " ++ show x ++ " Gold coins!!!!" --TODO task incomplete -makeMove = do +makeMove :: KnightTsk9 -> MonsterTsk9 -> IO b +makeMove knt mns = do putStrLn "Attack(A), Cast a spell to defend(D), Drink a health portion(H):" mv <- getLine case mv of - "A" -> "TODO attacked" - "D" -> "TODO defended" - "H" -> "TODO health potion" - _ -> "TODO invalid action" + "A" -> print "TODO attacked" + "D" -> print "TODO defended" + "H" -> print "TODO health potion" + _ -> print "TODO invalid action" + makeMove knt mns -keepFighting = do - -- do action - -- display status - makeMove +-- keepFighting = do +-- -- do action +-- -- display status +-- makeMove + +startFight :: IO b startFight = do - putStrln "Who is it that wants to fight Monster Gorba?" + putStrLn "Who is it that wants to fight Monster Gorba?" knt <- getLine - print "Welcome, " ++ knt ++ " Let's fight!!" - makeMove + print ("Welcome, " ++ knt ++ ". Let's fight Gorba!!") + makeMove KnightTsk9 {kntHealth = HealthTsk9 100, kntAttack = AttackTsk9 20, kntDefence = DefenceTsk9 10} MonsterTsk9 {mnstHealth = HealthTsk9 100, mnstAttack = AttackTsk9 20} + {- From a26c6b5c8956469a47488af7f1c29d0bf16da31d Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Tue, 25 Oct 2022 18:53:57 +1100 Subject: [PATCH 37/45] functioning Task9 --- src/Chapter3.hs | 102 +++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 41 deletions(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 4ca7327e9..88107b855 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -1154,68 +1154,88 @@ Implement data types and typeclasses, describing such a battle between two contestants, and write a function that decides the outcome of a fight! -} -newtype AttackTsk9 = AttackTsk9 Int -newtype HealthTsk9 = HealthTsk9 Int -newtype DefenceTsk9 = DefenceTsk9 Int +newtype AttackTsk9 = AttackTsk9 Int deriving (Show) +newtype HealthTsk9 = HealthTsk9 Int deriving (Show) +newtype DefenceTsk9 = DefenceTsk9 Int deriving (Show) data KnightTsk9 = KnightTsk9 { kntHealth :: HealthTsk9, kntAttack :: AttackTsk9, kntDefence :: DefenceTsk9 -} +} deriving (Show) data MonsterTsk9 = MonsterTsk9 { mnstHealth :: HealthTsk9, mnstAttack :: AttackTsk9 -} +} deriving (Show) -scoreTsk9 :: Int -> Int -> Int -scoreTsk9 x y - | x > y = x - y - | otherwise = 0 +scoreTsk9 :: HealthTsk9 -> AttackTsk9 -> HealthTsk9 +scoreTsk9 (HealthTsk9 x) (AttackTsk9 y) + | x > y = HealthTsk9 (x - y) + | otherwise = HealthTsk9 0 --- fireTsk9 :: KnightTsk9 -> MonsterTsk9 -> (KnightTsk9, MonsterTsk9) --- fireTsk9 kn (MonsterTsk9 0 ma) = (kn, MonsterTsk9 0 ma) -- monster is defeated, health 0 --- fireTsk9 (KnightTsk9 0 ka kd) mn = (KnightTsk9 0 ka kd, mn) -- knight is defeated, health 0 --- fireTsk9 (KnightTsk9 kh ka kd) (MonsterTsk9 mh ma) -- take turns to fire --- | kf == mf = fireTsk9 (KnightTsk9 kh ka kg (kf + 1)) (MonsterTsk9 (score mh ka) ma mg mf) --knight fires --- | otherwise = fireTsk9 (KnightTsk9 (score kh ma) ka kg kf) (MonsterTsk9 mh ma mg (mf + 1)) -- monster fires +defendTsk9 :: HealthTsk9 -> DefenceTsk9 -> HealthTsk9 +defendTsk9 (HealthTsk9 x) (DefenceTsk9 y) = HealthTsk9 (x + y) --- fightTsk9 :: (KnightTsk9, MonsterTsk9) -> Int --- fightTsk9 (KnightTsk9 _ _ kd , MonsterTsk9 0 _) = kg + mg -- monster loses --- fightTsk9 (KnightTsk9 0 _ _ , MonsterTsk9 {}) = -1 -- knight loses --- fightTsk9 (KnightTsk9 _ _ kd , MonsterTsk9 {}) = kg -- draw +fightTsk9 :: (KnightTsk9, MonsterTsk9) -> Int +fightTsk9 (KnightTsk9 {} , MonsterTsk9 (HealthTsk9 0) _ ) = 1 -- monster loses +fightTsk9 (KnightTsk9 (HealthTsk9 0) _ _ , MonsterTsk9 {}) = -1 -- knight loses +fightTsk9 _ = 0 -- draw -proclaimTsk9 :: Int -> String -proclaimTsk9 x - | x == 0 = "Uh oh, it was a draw" - | x == -1 = "Monster's tooooo gooood" - | otherwise = "Monster dies. Knight is rich. Has " ++ show x ++ " Gold coins!!!!" - --TODO task incomplete +proclaimOrDoTsk9 :: (KnightTsk9, MonsterTsk9) -> IO () +proclaimOrDoTsk9 mat = do + print mat + let res = fightTsk9 mat + if res == 0 + then makeMove mat + else if res == (-1) + then print "Monster wins" + else print "Knight wins" -makeMove :: KnightTsk9 -> MonsterTsk9 -> IO b -makeMove knt mns = do - putStrLn "Attack(A), Cast a spell to defend(D), Drink a health portion(H):" - mv <- getLine - case mv of - "A" -> print "TODO attacked" - "D" -> print "TODO defended" - "H" -> print "TODO health potion" - _ -> print "TODO invalid action" - makeMove knt mns +knightAttackTsk9 :: (KnightTsk9, MonsterTsk9) -> (KnightTsk9, MonsterTsk9) +knightAttackTsk9 (KnightTsk9 kh ka kd, MonsterTsk9 mh ma) = (KnightTsk9 kh ka kd, MonsterTsk9 (scoreTsk9 mh ka) ma) + +monsterAttackTsk9 :: (KnightTsk9, MonsterTsk9) -> (KnightTsk9, MonsterTsk9) +monsterAttackTsk9 (KnightTsk9 kh ka kd, MonsterTsk9 mh ma) = (KnightTsk9 (scoreTsk9 (defendTsk9 kh kd) ma) ka kd, MonsterTsk9 mh ma) --- keepFighting = do +increaseDefenceTsk9 :: (KnightTsk9, MonsterTsk9) -> (KnightTsk9, MonsterTsk9) +increaseDefenceTsk9 (KnightTsk9 kh ka (DefenceTsk9 kd), MonsterTsk9 mh ma) = (KnightTsk9 kh ka (DefenceTsk9 (kd + 100)), MonsterTsk9 mh ma) --- -- do action --- -- display status --- makeMove +drinkHealthTsk9 :: (KnightTsk9, MonsterTsk9) -> (KnightTsk9, MonsterTsk9) +drinkHealthTsk9 (KnightTsk9 (HealthTsk9 kh) ka kd, MonsterTsk9 mh ma) = (KnightTsk9 (HealthTsk9 (kh + 20)) ka kd, MonsterTsk9 mh ma) -startFight :: IO b + +makeMove :: (KnightTsk9, MonsterTsk9) -> IO () +makeMove (knt, mns) = do + putStrLn "Attack(A), Cast spell to increase defence(D), Drink health portion(H):" + mv <- getLine + case mv of + "a" -> do + let at = knightAttackTsk9 (knt, mns) + let mat = monsterAttackTsk9 at + proclaimOrDoTsk9 mat + + "d" -> do + let df = increaseDefenceTsk9 (knt, mns) + print df + print "Knight's defence just went up by 100." + let mat = monsterAttackTsk9 df + proclaimOrDoTsk9 mat + "h" -> do + let hd = drinkHealthTsk9 (knt, mns) + print hd + print "Knight's health just went up by 20." + let mat = monsterAttackTsk9 hd + proclaimOrDoTsk9 mat + _ -> print "invalid action, good bye" + +startFight :: IO () startFight = do putStrLn "Who is it that wants to fight Monster Gorba?" knt <- getLine print ("Welcome, " ++ knt ++ ". Let's fight Gorba!!") - makeMove KnightTsk9 {kntHealth = HealthTsk9 100, kntAttack = AttackTsk9 20, kntDefence = DefenceTsk9 10} MonsterTsk9 {mnstHealth = HealthTsk9 100, mnstAttack = AttackTsk9 20} + makeMove (KnightTsk9 {kntHealth = HealthTsk9 100, kntAttack = AttackTsk9 20, kntDefence = DefenceTsk9 10}, + MonsterTsk9 {mnstHealth = HealthTsk9 100, mnstAttack = AttackTsk9 60}) From 85200a24d131544c8defb43d84dcbeb05fb524cd Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Tue, 25 Oct 2022 21:42:43 +1100 Subject: [PATCH 38/45] Completed Chapter 3 --- src/Chapter3.hs | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index 88107b855..d049e174a 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -1157,6 +1157,7 @@ contestants, and write a function that decides the outcome of a fight! newtype AttackTsk9 = AttackTsk9 Int deriving (Show) newtype HealthTsk9 = HealthTsk9 Int deriving (Show) newtype DefenceTsk9 = DefenceTsk9 Int deriving (Show) +newtype KnightName = KnightName String deriving (Show) data KnightTsk9 = KnightTsk9 { kntHealth :: HealthTsk9, @@ -1182,12 +1183,14 @@ fightTsk9 (KnightTsk9 {} , MonsterTsk9 (HealthTsk9 0) _ ) = 1 -- monster loses fightTsk9 (KnightTsk9 (HealthTsk9 0) _ _ , MonsterTsk9 {}) = -1 -- knight loses fightTsk9 _ = 0 -- draw -proclaimOrDoTsk9 :: (KnightTsk9, MonsterTsk9) -> IO () -proclaimOrDoTsk9 mat = do +proclaimOrDoTsk9 :: KnightName -> (KnightTsk9, MonsterTsk9) -> IO () +proclaimOrDoTsk9 k mat = do + print "Monster attacks" print mat + putStr "\n" let res = fightTsk9 mat if res == 0 - then makeMove mat + then makeMove k mat else if res == (-1) then print "Monster wins" else print "Knight wins" @@ -1205,39 +1208,46 @@ drinkHealthTsk9 :: (KnightTsk9, MonsterTsk9) -> (KnightTsk9, MonsterTsk9) drinkHealthTsk9 (KnightTsk9 (HealthTsk9 kh) ka kd, MonsterTsk9 mh ma) = (KnightTsk9 (HealthTsk9 (kh + 20)) ka kd, MonsterTsk9 mh ma) -makeMove :: (KnightTsk9, MonsterTsk9) -> IO () -makeMove (knt, mns) = do - putStrLn "Attack(A), Cast spell to increase defence(D), Drink health portion(H):" +makeMove :: KnightName -> (KnightTsk9, MonsterTsk9) -> IO () +makeMove (KnightName k) (knt, mns) = do + putStrLn "Attack(a), Cast spell to increase defence(d), Drink health potion(h):" mv <- getLine case mv of "a" -> do + print (k ++ " attacks") let at = knightAttackTsk9 (knt, mns) + print at let mat = monsterAttackTsk9 at - proclaimOrDoTsk9 mat + proclaimOrDoTsk9 (KnightName k) mat "d" -> do + print (k ++ " casts spell. Defence is increased") let df = increaseDefenceTsk9 (knt, mns) print df - print "Knight's defence just went up by 100." + print (k ++ "'s defence just went up by 100.") let mat = monsterAttackTsk9 df - proclaimOrDoTsk9 mat + proclaimOrDoTsk9 (KnightName k) mat "h" -> do + print (k ++ "Knight drinks health potion.") let hd = drinkHealthTsk9 (knt, mns) print hd - print "Knight's health just went up by 20." + print (k ++ "Knight's health just went up by 20.") let mat = monsterAttackTsk9 hd - proclaimOrDoTsk9 mat - _ -> print "invalid action, good bye" + proclaimOrDoTsk9 (KnightName k) mat + "X" -> print "Goodbye" + _ -> print "invalid action, Try again. Press X to exit" startFight :: IO () startFight = do - putStrLn "Who is it that wants to fight Monster Gorba?" + putStrLn "Who is it that wants to fight Monster Rakshas?" knt <- getLine - print ("Welcome, " ++ knt ++ ". Let's fight Gorba!!") - makeMove (KnightTsk9 {kntHealth = HealthTsk9 100, kntAttack = AttackTsk9 20, kntDefence = DefenceTsk9 10}, - MonsterTsk9 {mnstHealth = HealthTsk9 100, mnstAttack = AttackTsk9 60}) + print ("Welcome, " ++ knt ++ ". Let's fight Rakshas!!") + let start = (KnightTsk9 {kntHealth = HealthTsk9 100, kntAttack = AttackTsk9 20, kntDefence = DefenceTsk9 10}, MonsterTsk9 {mnstHealth = HealthTsk9 100, mnstAttack = AttackTsk9 60}) + print start + makeMove (KnightName knt) start - +-- to play the game, +-- startFight {- You did it! Now it is time to open pull request with your changes From 2416836bc479ec836c911cf594439bbaef143407 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Tue, 25 Oct 2022 22:59:23 +1100 Subject: [PATCH 39/45] completed Task2: Chapter 4 --- src/Chapter4.hs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index 205322224..0e064197b 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -114,22 +114,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 :: (* -> *) -> * -} @@ -293,7 +301,9 @@ 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 g) = Trap g + fmap f (Reward c) = Reward (f c) + {- | =⚔️= Task 3 @@ -307,6 +317,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 c d) = Cons (f c) (fmap f d) + {- | =🛡= Applicative From d857b87ef1b49884d7f366a60afd1ff5301965d5 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Wed, 26 Oct 2022 13:03:41 +1100 Subject: [PATCH 40/45] updated Task 9, Chapter 3 --- src/Chapter3.hs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Chapter3.hs b/src/Chapter3.hs index d049e174a..e00f865a5 100644 --- a/src/Chapter3.hs +++ b/src/Chapter3.hs @@ -1178,10 +1178,12 @@ scoreTsk9 (HealthTsk9 x) (AttackTsk9 y) defendTsk9 :: HealthTsk9 -> DefenceTsk9 -> HealthTsk9 defendTsk9 (HealthTsk9 x) (DefenceTsk9 y) = HealthTsk9 (x + y) -fightTsk9 :: (KnightTsk9, MonsterTsk9) -> Int -fightTsk9 (KnightTsk9 {} , MonsterTsk9 (HealthTsk9 0) _ ) = 1 -- monster loses -fightTsk9 (KnightTsk9 (HealthTsk9 0) _ _ , MonsterTsk9 {}) = -1 -- knight loses -fightTsk9 _ = 0 -- draw + +data Result = Draw | Lose | Win +fightTsk9 :: (KnightTsk9, MonsterTsk9) -> Result +fightTsk9 (KnightTsk9 {} , MonsterTsk9 (HealthTsk9 0) _ ) = Win -- Knight wins +fightTsk9 (KnightTsk9 (HealthTsk9 0) _ _ , MonsterTsk9 {}) = Lose -- knight loses +fightTsk9 _ = Draw proclaimOrDoTsk9 :: KnightName -> (KnightTsk9, MonsterTsk9) -> IO () proclaimOrDoTsk9 k mat = do @@ -1189,11 +1191,10 @@ proclaimOrDoTsk9 k mat = do print mat putStr "\n" let res = fightTsk9 mat - if res == 0 - then makeMove k mat - else if res == (-1) - then print "Monster wins" - else print "Knight wins" + case res of + Draw -> makeMove k mat + Lose -> print "Monster wins" + Win -> print "Knight wins" knightAttackTsk9 :: (KnightTsk9, MonsterTsk9) -> (KnightTsk9, MonsterTsk9) knightAttackTsk9 (KnightTsk9 kh ka kd, MonsterTsk9 mh ma) = (KnightTsk9 kh ka kd, MonsterTsk9 (scoreTsk9 mh ka) ma) From f60c32eb9f1f53f85dc548b7dcc9528cd1b76867 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Fri, 28 Oct 2022 23:43:28 +1100 Subject: [PATCH 41/45] reached Monads! --- src/Chapter4.hs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index 0e064197b..aafac775d 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -41,6 +41,7 @@ Perfect. Let's crush this! {-# LANGUAGE InstanceSigs #-} module Chapter4 where +import Data.Char {- | =🛡= Kinds @@ -487,12 +488,14 @@ 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 c) _= Trap c + (<*>) _ (Trap c) = Trap c + (<*>) (Reward f) (Reward c) = Reward (f c) -{- | +{- | =⚔️= Task 5 Implement the 'Applicative' instance for our 'List' type. @@ -613,9 +616,17 @@ concepts in the end. Implement the 'Monad' instance for our 'Secret' type. -} -instance Monad (Secret e) where +upper :: Char -> Secret e Char +upper x = Reward (Data.Char.toUpper x) + +multiplyBy5 :: Int -> Secret e Int +multiplyBy5 x = Reward (x * 5) + + +instance Monad (Secret e ) where (>>=) :: Secret e a -> (a -> Secret e b) -> Secret e b - (>>=) = error "bind Secret: Not implemented!" + (>>=) (Trap c) _ = Trap c + (>>=) (Reward c) f = f c {- | =⚔️= Task 7 From b5380f991a2304cce0faedf5774e47eba528241e Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 29 Oct 2022 13:43:45 +1100 Subject: [PATCH 42/45] completed Task8: Chapter 4. tests passing --- src/Chapter4.hs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index aafac775d..03b291d57 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -507,6 +507,14 @@ Implement the 'Applicative' instance for our 'List' type. type. -} +instance Applicative List where + pure :: a -> List a + pure c = Cons c Empty + (<*>) :: List (a -> b) -> List a -> List b + (<*>) _ Empty = Empty + (<*>) Empty _ = Empty + (<*>) (Cons g _) (Cons c d) = Cons (g c) ((<*>) (Cons g Empty) d) + {- | =🛡= Monad @@ -654,8 +662,23 @@ Can you implement a monad version of AND, polymorphic over any monad? 🕯 HINT: Use "(>>=)", "pure" and anonymous function -} + + +-- this would fail in Just Flase - Nothing case +-- andM :: (Monad m) => m Bool -> m Bool -> m Bool +-- andM n c = do +-- x <- n +-- y <- c +-- pure (x && y) + +checkBool :: (Monad m) => m Bool -> Bool-> m Bool +checkBool x True = x +checkBool _ False = pure False + + andM :: (Monad m) => m Bool -> m Bool -> m Bool -andM = error "andM: Not implemented!" +andM n c = n >>= checkBool c + {- | =🐉= Task 9*: Final Dungeon Boss From 3d4d5e4989bbc4decbc0dc20acd9817f2892c4f1 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sat, 29 Oct 2022 18:13:40 +1100 Subject: [PATCH 43/45] working on the last task --- src/Chapter4.hs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index 03b291d57..85ba8f0bb 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -664,7 +664,7 @@ Can you implement a monad version of AND, polymorphic over any monad? -} --- this would fail in Just Flase - Nothing case +-- this would fail in Just False - Nothing case -- andM :: (Monad m) => m Bool -> m Bool -> m Bool -- andM n c = do -- x <- n @@ -679,6 +679,16 @@ checkBool _ False = pure False andM :: (Monad m) => m Bool -> m Bool -> m Bool andM n c = n >>= checkBool c +boolInt :: (Monad m) => Bool -> m Int +boolInt True = pure 1 +boolInt False = pure 0 + +intString :: (Monad m) => Int -> m [Char] +intString 0 = pure "fail" +intString _ = pure "passes" + +typeM :: (Monad m) => m Bool -> m [Char] +typeM b = b >>= boolInt >>= intString {- | =🐉= Task 9*: Final Dungeon Boss @@ -722,6 +732,19 @@ Specifically, ❃ Implement the function to convert Tree to list -} +data Node a b = Leaf a | Node b + +data BinTree a b = BinTree (Node a b) (Node a b) + +instance Functor (BinTree e) where + fmap :: (a -> b) -> BinTree e a -> BinTree e b + fmap todo + + +-- instance Functor (Secret e) where +-- fmap :: (a -> b) -> Secret e a -> Secret e b +-- fmap _ (Trap g) = Trap g +-- fmap f (Reward c) = Reward (f c) {- You did it! Now it is time to open pull request with your changes From e38d4f208096e1ef1388fe73eaa102d9ba3021e8 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Sun, 30 Oct 2022 21:20:04 +1100 Subject: [PATCH 44/45] completed Chapter 4, all tests pass --- src/Chapter4.hs | 57 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index 85ba8f0bb..e70c8b820 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -732,19 +732,50 @@ Specifically, ❃ Implement the function to convert Tree to list -} -data Node a b = Leaf a | Node b - -data BinTree a b = BinTree (Node a b) (Node a b) - -instance Functor (BinTree e) where - fmap :: (a -> b) -> BinTree e a -> BinTree e b - fmap todo - - --- instance Functor (Secret e) where --- fmap :: (a -> b) -> Secret e a -> Secret e b --- fmap _ (Trap g) = Trap g --- fmap f (Reward c) = Reward (f c) +data Node a = Leaf | Node a deriving (Show) + +data BinTree a = BinTree (Node a ) (BinTree a ) (BinTree a ) | TreeLeaf deriving (Show) + +instance Functor BinTree where + fmap :: (a -> b) -> BinTree a -> BinTree b + fmap _ TreeLeaf = TreeLeaf + fmap g (BinTree Leaf x y) = BinTree Leaf (fmap g x) (fmap g y) + fmap g (BinTree (Node d) x y) = BinTree (Node (g d)) (fmap g x) (fmap g y) + + +instance Applicative BinTree where + pure :: a -> BinTree a + pure x = BinTree (Node x) TreeLeaf TreeLeaf + (<*>) :: BinTree (a -> b) -> BinTree a -> BinTree b + (<*>) _ TreeLeaf = TreeLeaf + (<*>) TreeLeaf _ = TreeLeaf + (<*>) (BinTree Leaf _ _) _ = TreeLeaf + (<*>) (BinTree (Node g) _ _) (BinTree Leaf x y) = BinTree Leaf (fmap g x) (fmap g y) + (<*>) (BinTree (Node g) _ _) (BinTree (Node d) x y) = BinTree (Node (g d)) (fmap g x) (fmap g y) + + +instance Monad BinTree where + (>>=) :: BinTree a -> (a -> BinTree b) -> BinTree b + (>>=) TreeLeaf _ = TreeLeaf + (>>=) (BinTree Leaf x y ) g = BinTree Leaf (x >>= g) (y >>= g) + (>>=) (BinTree (Node c) _ _ ) g = g c + +reverseTree :: BinTree a -> BinTree a +reverseTree TreeLeaf = TreeLeaf +reverseTree (BinTree c x y) = BinTree c (reverseTree y) (reverseTree x) + + + +treeToList :: BinTree a -> [a] +treeToList TreeLeaf = [] +treeToList (BinTree Leaf x y ) = treeToList x ++ treeToList y +treeToList (BinTree (Node c) x y ) = c : treeToList x ++ treeToList y + +-- example +-- treeToList (BinTree (Node 4) (BinTree (Node 5) (BinTree (Node 6) TreeLeaf TreeLeaf) TreeLeaf) (BinTree (Node 10) TreeLeaf TreeLeaf)) +-- [4,5,6,10] +-- treeToList (BinTree (Node "Mary") (BinTree (Node "had") (BinTree (Node "a") TreeLeaf TreeLeaf) TreeLeaf) (BinTree (Node " lamb") TreeLeaf TreeLeaf)) +-- ["Mary","had","a"," lamb"] {- You did it! Now it is time to open pull request with your changes From 59ad927af5ff3a3a5d8fe4d135c91ec715c8a7a3 Mon Sep 17 00:00:00 2001 From: yebowhatsay Date: Mon, 31 Oct 2022 12:48:22 +1100 Subject: [PATCH 45/45] added return to Monad --- src/Chapter4.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Chapter4.hs b/src/Chapter4.hs index e70c8b820..88558eecb 100644 --- a/src/Chapter4.hs +++ b/src/Chapter4.hs @@ -755,6 +755,8 @@ instance Applicative BinTree where instance Monad BinTree where + return :: a -> BinTree a + return = pure (>>=) :: BinTree a -> (a -> BinTree b) -> BinTree b (>>=) TreeLeaf _ = TreeLeaf (>>=) (BinTree Leaf x y ) g = BinTree Leaf (x >>= g) (y >>= g)