-
-
Notifications
You must be signed in to change notification settings - Fork 847
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chapter 1 Tasks #557
base: main
Are you sure you want to change the base?
Chapter 1 Tasks #557
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -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 | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
True :: Bool | ||||||||
>>> :t 'a' | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
'a' :: Char | ||||||||
>>> :t 42 | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
42 :: Num a => a | ||||||||
|
||||||||
A pair of boolean and char: | ||||||||
>>> :t (True, 'x') | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
(True, 'x') :: (Bool, Char) | ||||||||
|
||||||||
Boolean negation: | ||||||||
>>> :t not | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
not :: Bool -> Bool | ||||||||
|
||||||||
Boolean 'and' operator: | ||||||||
>>> :t (&&) | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
(&&) :: Bool -> Bool -> Bool | ||||||||
|
||||||||
Addition of two numbers: | ||||||||
>>> :t (+) | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
(+) :: Num a => a -> a -> a | ||||||||
|
||||||||
Maximum of two values: | ||||||||
>>> :t max | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
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 | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
3 | ||||||||
|
||||||||
>>> 10 - 15 | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
-5 | ||||||||
|
||||||||
>>> 10 - (-5) -- negative constants require () | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
15 | ||||||||
|
||||||||
>>> (3 + 5) < 10 | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
True | ||||||||
|
||||||||
>>> True && False | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
False | ||||||||
|
||||||||
>>> 10 < 20 || 20 < 5 | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
True | ||||||||
|
||||||||
>>> 2 ^ 10 -- power | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
1024 | ||||||||
|
||||||||
>>> not False | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
True | ||||||||
|
||||||||
>>> div 20 3 -- integral division | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
6 | ||||||||
|
||||||||
>>> mod 20 3 -- integral division remainder | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
2 | ||||||||
|
||||||||
>>> max 4 10 | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
10 | ||||||||
|
||||||||
>>> min 5 (max 1 2) | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
2 | ||||||||
|
||||||||
>>> max (min 1 10) (min 5 7) | ||||||||
<INSERT THE RESULT INSTEAD OF THE TEXT> | ||||||||
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 :: Num a => a -> a -> a | ||||||||
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 :: Integral a => a -> a | ||||||||
lastDigit n = abs 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 :: Ord a => a -> a -> a -> a | ||||||||
mid x y z | ||||||||
| x <= y && x > z || x >= y && x < z = x | ||||||||
| y <= x && y > z || y >= x && y < z = y | ||||||||
| otherwise = z | ||||||||
|
||||||||
{- | | ||||||||
=⚔️= Task 8 | ||||||||
|
@@ -568,7 +574,10 @@ True | |||||||
>>> isVowel 'x' | ||||||||
False | ||||||||
-} | ||||||||
isVowel c = error "isVowel: not implemented!" | ||||||||
isVowel :: Char -> Bool | ||||||||
isVowel c | ||||||||
| c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' = True | ||||||||
| otherwise = False | ||||||||
Comment on lines
+579
to
+580
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this is right! As
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Oh, yeah :) I've just forgot it for a moment)) |
||||||||
|
||||||||
|
||||||||
{- | | ||||||||
|
@@ -632,7 +641,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 :: Integral a => a -> a | ||||||||
sumLast2 n = b + a where | ||||||||
a = an `mod` 10 | ||||||||
b = (an `div` 10) `mod` 10 | ||||||||
Comment on lines
+646
to
+647
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a wonderful solution! 👏🏼 You correctly noticed that it is the One hint to make your solution even shorter: you can see that you use both: mod m 10
div m 10 The standard library has the So you could write it this way: (x, y) = divMod m 10 You can see how we could pattern match on the pair 🙂 |
||||||||
an = abs n | ||||||||
|
||||||||
|
||||||||
{- | | ||||||||
|
@@ -653,7 +666,8 @@ 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 :: Integral t => t -> t | ||||||||
firstDigit n = let an = abs n in if an < 10 then an else firstDigit (an `div` 10) | ||||||||
|
||||||||
|
||||||||
{- | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -136,42 +136,52 @@ 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,30 +196,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!"] | ||
|
||
|
||
|
||
|
@@ -336,7 +359,9 @@ from it! | |
ghci> :l src/Chapter2.hs | ||
-} | ||
subList :: Int -> Int -> [a] -> [a] | ||
subList = error "subList: Not implemented!" | ||
subList a b xs | ||
| a < 0 || b < 0 = [] | ||
| otherwise = take (b - a + 1) (drop a xs) | ||
|
||
{- | | ||
=⚔️= Task 4 | ||
|
@@ -349,7 +374,8 @@ 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 (length l `div` 2) l | ||
|
||
|
||
{- | | ||
|
@@ -501,7 +527,9 @@ True | |
>>> isThird42 [42, 42, 0, 42] | ||
False | ||
-} | ||
isThird42 = error "isThird42: Not implemented!" | ||
isThird42 :: (Eq a, Num a) => [a] -> Bool | ||
isThird42 (_ : _ : 42 : _) = True | ||
isThird42 _ = False | ||
|
||
|
||
{- | | ||
|
@@ -606,7 +634,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 | ||
|
||
|
||
{- | | ||
|
@@ -621,7 +650,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 :: [a] -> [a] | ||
takeEven [] = [] | ||
takeEven [x] = [x] | ||
takeEven (x:_:xs) = x : takeEven xs | ||
Comment on lines
+654
to
+656
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's great! Note, that in the first two cases you return the list as it is. In this case, you could also right the function with just two cases, by switching them around: takeEven (x:_:xs) = x : takeEven xs
takeEven xs = xs Though, I think that your solution is more explicit, therefore, more readable! 👏🏼 |
||
|
||
{- | | ||
=🛡= Higher-order functions | ||
|
@@ -728,7 +760,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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great! 👍🏼 |
||
|
||
{- | | ||
=⚔️= Task 9 | ||
|
@@ -741,7 +773,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 :: (Foldable t, Eq a) => a -> [t a] -> [t a] | ||
contains n = filter (n `elem`) | ||
|
||
|
||
{- | | ||
|
@@ -781,13 +814,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 :: Num c => [c] -> [c] -> [c] | ||
pairMul = zipWith (*) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eta-reduction award 🏆 |
||
|
||
{- | | ||
=🛡= Lazy evaluation | ||
|
@@ -842,7 +877,10 @@ list. | |
|
||
🕯 HINT: Use the 'cycle' function | ||
-} | ||
rotate = error "rotate: Not implemented!" | ||
rotate :: Int -> [a] -> [a] | ||
rotate n l | ||
| n < 0 = [] | ||
| otherwise = take (length l) (drop n (cycle l)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome! You can optimise it a little bit by using |
||
|
||
{- | | ||
=💣= Task 12* | ||
|
@@ -858,7 +896,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 [] = [] | ||
rewind l = rewind' [] l where | ||
rewind' reversed [] = reversed | ||
rewind' reversed (x:xs) = rewind' (x : reversed) xs | ||
Comment on lines
+901
to
+903
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fantastic solution 🎉 Nothe, that there is no need to pattern match on the empty list in the |
||
|
||
|
||
{- | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We explain
Num
in the following chapters, so you are one step ahead 😸In here
Int -> Int -> Int
would also work, as a more specific type 🙂