From 1c0aceb64b1627cb11f71a70921ccf2c32c42294 Mon Sep 17 00:00:00 2001 From: cypress Date: Thu, 25 Jan 2024 20:03:26 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=8E=89=20chapter1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Chapter1.hs | 71 +++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 406deeaca..a0424ddf0 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 a => a 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. @@ -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 @@ -490,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 :: Int -> Int +lastDigit n = n `mod` 10 {- | @@ -520,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 = if abs x < abs y then x else y {- | @@ -554,7 +556,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 :: Int -> Int -> Int -> Int +mid x y z + | x <= y && y <= z = y + | x >= y && y >= z = y + | otherwise = mid y z x {- | =⚔️= Task 8 @@ -568,7 +574,8 @@ True >>> isVowel 'x' False -} -isVowel c = error "isVowel: not implemented!" +isVowel :: Char -> Bool +isVowel = (`elem` "aoeiuv") {- | @@ -632,7 +639,11 @@ 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 x = + let last = x `mod` 10 + secondlast = x `mod` 100 `div` 10 + in last + secondlast {- | @@ -653,8 +664,10 @@ 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 x + | x `div` 10 == 0 = x + | otherwise = firstDigit (x `div` 10) {- You did it! Now it is time to open a pull request with your changes From 286780edb911485db49af06b8e42ee510a692402 Mon Sep 17 00:00:00 2001 From: cypress Date: Thu, 25 Jan 2024 20:35:05 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=90=9B=20fix=20parse=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Chapter1.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index a0424ddf0..1b40212bc 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -642,7 +642,7 @@ specifying complex expressions. sumLast2 :: Int -> Int sumLast2 x = let last = x `mod` 10 - secondlast = x `mod` 100 `div` 10 + secondlast = x `mod` 100 `div` 10 in last + secondlast From c57a80edc66b683e715ce6595de3c677e2714975 Mon Sep 17 00:00:00 2001 From: cypress Date: Thu, 25 Jan 2024 20:47:00 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=90=9B=20fix=20negative?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Chapter1.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 1b40212bc..a4be5272b 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 :: Int -> Int -lastDigit n = n `mod` 10 +lastDigit = (`mod` 10) . abs {- | @@ -641,8 +641,9 @@ specifying complex expressions. sumLast2 :: Int -> Int sumLast2 x = - let last = x `mod` 10 - secondlast = x `mod` 100 `div` 10 + let ax = abs x + last = ax `mod` 10 + secondlast = ax `mod` 100 `div` 10 in last + secondlast From 0846d37dd086ce72407f3432e88dee21be60cce4 Mon Sep 17 00:00:00 2001 From: cypress Date: Thu, 25 Jan 2024 22:33:00 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=90=9B=20fix=20another=20negative?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Chapter1.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index a4be5272b..a5d331b3c 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -667,8 +667,9 @@ aren't ready for this boss yet! firstDigit :: Int -> Int firstDigit x - | x `div` 10 == 0 = x - | otherwise = firstDigit (x `div` 10) + | absx `div` 10 == 0 = absx + | otherwise = firstDigit (absx `div` 10) + where absx = abs x {- You did it! Now it is time to open a pull request with your changes From 7a65dcb4241d0e8ca1c4f6c270888516370dd3a4 Mon Sep 17 00:00:00 2001 From: cypress Date: Fri, 26 Jan 2024 00:35:46 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=8E=89=20chapter2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Chapter2.hs | 91 ++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index b98ceaf7d..4e2426c21 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -136,43 +136,43 @@ 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" :: String 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 - +take :: 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 -} @@ -186,31 +186,31 @@ 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 @@ -336,7 +336,10 @@ from it! ghci> :l src/Chapter2.hs -} subList :: Int -> Int -> [a] -> [a] -subList = error "subList: Not implemented!" +subList x y [] = [] +subList x y xs + | x > y = [] + | otherwise = (drop x) . (take (y+1)) $ xs {- | =⚔️= Task 4 @@ -349,7 +352,9 @@ Implement a function that returns only the first half of a given list. "b" -} -- PUT THE FUNCTION TYPE IN HERE -firstHalf l = error "firstHalf: Not implemented!" +firstHalf :: [a] -> [a] +firstHalf l = take half l + where half = length l `div` 2 {- | @@ -501,7 +506,9 @@ True >>> isThird42 [42, 42, 0, 42] False -} -isThird42 = error "isThird42: Not implemented!" +isThird42 :: [Int] -> Bool +isThird42 (_:_:x:xs) = x == 42 +isThird42 _ = False {- | @@ -606,7 +613,8 @@ Implement a function that duplicates each element of the list -} duplicate :: [a] -> [a] -duplicate = error "duplicate: Not implemented!" +duplicate (x:xs) = x:x:duplicate xs +duplicate _ = [] {- | @@ -621,7 +629,9 @@ 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 (x:y:xs) = x : takeEven xs +takeEven x = x {- | =🛡= Higher-order functions @@ -728,7 +738,9 @@ value of the element itself 🕯 HINT: Use combination of 'map' and 'replicate' -} smartReplicate :: [Int] -> [Int] -smartReplicate l = error "smartReplicate: Not implemented!" +smartReplicate = concat . map replicateN + where replicateN :: Int -> [Int] + replicateN n = replicate n n {- | =⚔️= Task 9 @@ -741,7 +753,8 @@ 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 :: Int -> [[Int]] -> [[Int]] +contains n xs = filter (elem n) xs {- | @@ -781,13 +794,16 @@ 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 = (10 `div`) -- TODO: type ;) -listElementsLessThan x l = filter (< x) l +listElementsLessThan :: Int -> [Int] -> [Int] +listElementsLessThan = filter . (>) -- why? +-- listElementsLessThan x l = filter (< x) l -- Can you eta-reduce this one??? -pairMul xs ys = zipWith (*) xs ys +pairMul :: [Int] -> [Int] -> [Int] +pairMul = zipWith (*) {- | =🛡= Lazy evaluation @@ -842,7 +858,10 @@ list. 🕯 HINT: Use the 'cycle' function -} -rotate = error "rotate: Not implemented!" +rotate :: Int -> [a] -> [a] +rotate n xs + | n < 0 = [] + | otherwise = take (length xs) $ drop n $ cycle xs {- | =💣= Task 12* @@ -858,7 +877,9 @@ 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 [] = [] +rewind (x:xs) = rewind xs ++ [x] {-