From ee10bbc3fdc46936c28b128e06bcb3777eaf3d0f Mon Sep 17 00:00:00 2001 From: "G. Reiter" Date: Fri, 14 Oct 2022 00:12:29 +0200 Subject: [PATCH 01/13] Part 1 for Chapter 1 --- src/Chapter1.hs | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 04fed0db..017cb63e 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 - +False :: 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) @@ -448,8 +449,9 @@ Implement the function that takes an integer value and returns the next 'Int'. every type 。.☆.*。. No need to worry much about "error" here, just replace the 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 +492,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 = mod n 10 {- | From 51b36ed4ee2d4792ba94cd1a90f3d2141d6c548a Mon Sep 17 00:00:00 2001 From: Guntbert Reiter Date: Fri, 14 Oct 2022 21:48:12 +0200 Subject: [PATCH 02/13] Finished Chapter1 --- src/Chapter1.hs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Chapter1.hs b/src/Chapter1.hs index 017cb63e..be16d318 100644 --- a/src/Chapter1.hs +++ b/src/Chapter1.hs @@ -72,6 +72,7 @@ the `.hs` extension. -} module Chapter1 where +import Data.List {- | In Haskell, we have __expressions__. Expressions can be represented by some primitive values (numbers: 1, 100; characters: 'a', 'z'; booleans: True, False; @@ -209,7 +210,7 @@ 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 -False :: Bool +True :: Bool >>> :t 'a' 'a' :: Char >>> :t 42 @@ -523,7 +524,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) {- | @@ -556,8 +557,8 @@ 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 = head (tail(sort[x,y,z])) {- | =⚔️= Task 8 @@ -571,7 +572,10 @@ True >>> isVowel 'x' False -} -isVowel c = error "isVowel: not implemented!" +isVowel :: Char -> Bool +isVowel c + | elem c ['a', 'e', 'i', 'o', 'u'] = True + | otherwise = False {- | @@ -634,8 +638,11 @@ Implement a function that returns the sum of the last two digits of a number. 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 digit1 = mod n 10 + digit2 = mod (div n 10) 10 + in digit1 + digit2 {- | @@ -656,7 +663,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 n + | abs n < 10 = n + | otherwise = firstDigit (div n 10) {- From f9206b3c1a5f0e8723e414625d62baf2a122418a Mon Sep 17 00:00:00 2001 From: "G. Reiter" Date: Sat, 15 Oct 2022 00:36:50 +0200 Subject: [PATCH 03/13] Chapter2 - the easy part --- src/Chapter2.hs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index f7c02ce2..57814d8b 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" :: [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 - +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,30 +186,43 @@ 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!"] From 8963802a0bc0baa1ff3f0150afb7124b5557201e Mon Sep 17 00:00:00 2001 From: Guntbert Reiter Date: Sat, 15 Oct 2022 18:18:07 +0200 Subject: [PATCH 04/13] Next 2 functions --- src/Chapter2.hs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 57814d8b..0ca2e751 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -349,7 +349,9 @@ from it! ghci> :l src/Chapter2.hs -} subList :: Int -> Int -> [a] -> [a] -subList = error "subList: Not implemented!" +subList start stop list + | start < 0 || stop < 0 || stop < start = [] + | otherwise = drop start (take (stop+1) list) {- | =⚔️= Task 4 @@ -362,9 +364,10 @@ 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 = + let wantedLen = div (length l) 2 + in take wantedLen l {- | =🛡= Pattern matching From dd7d40e27e73333f5638be6e77cc0f1bc1d7a007 Mon Sep 17 00:00:00 2001 From: Guntbert Reiter Date: Sat, 15 Oct 2022 19:45:47 +0200 Subject: [PATCH 05/13] Task 5 --- src/Chapter2.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 0ca2e751..7a0a646e 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -517,7 +517,9 @@ True >>> isThird42 [42, 42, 0, 42] False -} -isThird42 = error "isThird42: Not implemented!" +isThird42 :: [Int] -> Bool +isThird42 (_:_:42:_) = True +isThird42 _ = False {- | From 1abfe4b414e6674937056af5548bd90d3047f31e Mon Sep 17 00:00:00 2001 From: Guntbert Reiter Date: Sat, 15 Oct 2022 21:13:18 +0200 Subject: [PATCH 06/13] Task 6 --- src/Chapter2.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 7a0a646e..edebc28c 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(dup)) {- =🛡= Imports @@ -624,7 +625,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 ed54af7e628ba74674ab7da490dbf5ec2a03a078 Mon Sep 17 00:00:00 2001 From: Guntbert Reiter Date: Sun, 16 Oct 2022 18:28:35 +0200 Subject: [PATCH 07/13] Task 6 using pattern matching --- src/Chapter2.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index edebc28c..1c0bc5c9 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -641,7 +641,10 @@ 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 [] = [] +takeEven (x:y:xs) = x : takeEven xs +takeEven (x:xs) = x : takeEven xs {- | =🛡= Higher-order functions From d9237ec774cea5015b12ce246fa1ab6cdf5c2c0e Mon Sep 17 00:00:00 2001 From: "G. Reiter" Date: Mon, 17 Oct 2022 22:05:29 +0200 Subject: [PATCH 08/13] Task: smartReplicate --- src/Chapter2.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 1c0bc5c9..93561081 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -751,7 +751,7 @@ value of the element itself 🕯 HINT: Use combination of 'map' and 'replicate' -} smartReplicate :: [Int] -> [Int] -smartReplicate l = error "smartReplicate: Not implemented!" +smartReplicate l = concat (map (\x -> replicate x x) l) {- | =⚔️= Task 9 From 91f33d6b3313a097a101e77ce8a27e195e44840e Mon Sep 17 00:00:00 2001 From: "G. Reiter" Date: Mon, 17 Oct 2022 22:50:44 +0200 Subject: [PATCH 09/13] Task: contains How do I determine the correct function type? --- src/Chapter2.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 93561081..32d6b02b 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -764,7 +764,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 :: Int -> [Int] -> [Int] +contains :: (Foldable t, Eq a) => a -> [t a] -> [t a] +contains n lists = filter (elem n ) lists {- | From 6736649a7a9c012572524bb9047b90416782359b Mon Sep 17 00:00:00 2001 From: "G. Reiter" Date: Mon, 17 Oct 2022 23:12:24 +0200 Subject: [PATCH 10/13] Task: eta-reduction --- src/Chapter2.hs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 32d6b02b..6fdd6c40 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -806,13 +806,14 @@ 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 :: Int -> [Int] -> [Int] +listElementsLessThan x = filter (< x) -- Can you eta-reduce this one??? -pairMul xs ys = zipWith (*) xs ys +pairMul = zipWith (*) {- | =🛡= Lazy evaluation From 46745335f428835824dbf5b1c06ea106168d89f7 Mon Sep 17 00:00:00 2001 From: "G. Reiter" Date: Tue, 18 Oct 2022 00:05:54 +0200 Subject: [PATCH 11/13] Implement all upto 'rewind' --- src/Chapter2.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 6fdd6c40..329464f3 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -868,7 +868,10 @@ list. 🕯 HINT: Use the 'cycle' function -} -rotate = error "rotate: Not implemented!" +rotate :: Int -> [Int] -> [Int] +rotate n list + | n < 0 = [] + | otherwise = take (length list) (drop n (cycle list)) {- | =💣= Task 12* From a5bf58bc4ec10d69c28578442bca85ed1728fb94 Mon Sep 17 00:00:00 2001 From: "G. Reiter" Date: Tue, 18 Oct 2022 23:27:23 +0200 Subject: [PATCH 12/13] And now rewind works as well --- src/Chapter2.hs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 329464f3..103b6fed 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -887,7 +887,13 @@ 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 l = go l [] + where + go :: [a] -> [a] -> [a] + go [] acc = acc + go (x:xs) acc = go xs (x:acc) + {- From f0fde6989b0b033887a16cf680dae5548e8366ad Mon Sep 17 00:00:00 2001 From: "G. Reiter" Date: Tue, 18 Oct 2022 23:32:52 +0200 Subject: [PATCH 13/13] Get rid of some warnings --- src/Chapter2.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Chapter2.hs b/src/Chapter2.hs index 103b6fed..5b863280 100644 --- a/src/Chapter2.hs +++ b/src/Chapter2.hs @@ -39,7 +39,7 @@ Now, if you are ready, bring it on! -} module Chapter2 where -import GHC.IO.Device (IODevice(dup)) +-- import GHC.IO.Device (IODevice(dup)) {- =🛡= Imports @@ -643,7 +643,7 @@ Write a function that takes elements of a list only in even positions. -} takeEven :: [Int]-> [Int] takeEven [] = [] -takeEven (x:y:xs) = x : takeEven xs +takeEven (x:_:xs) = x : takeEven xs takeEven (x:xs) = x : takeEven xs {- | @@ -813,6 +813,7 @@ listElementsLessThan :: Int -> [Int] -> [Int] listElementsLessThan x = filter (< x) -- Can you eta-reduce this one??? +pairMul :: [Int] -> [Int] -> [Int] pairMul = zipWith (*) {- |