-
-
Notifications
You must be signed in to change notification settings - Fork 849
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
Complete chapter 2 #534
base: main
Are you sure you want to change the base?
Complete chapter 2 #534
Changes from all commits
db32368
92f21a2
f49ac11
a6a9a65
4f71b40
ce8d66b
1bd5005
cd37165
878e071
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 | ||||
---|---|---|---|---|---|---|
|
@@ -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,32 +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!"] | ||||||
|
||||||
👩🔬 Haskell has a lot of syntax sugar. In the case with lists, any | ||||||
list literal like "[3, 1, 2]" is syntax sugar for prepending elements | ||||||
|
@@ -336,7 +347,8 @@ from it! | |||||
ghci> :l src/Chapter2.hs | ||||||
-} | ||||||
subList :: Int -> Int -> [a] -> [a] | ||||||
subList = error "subList: Not implemented!" | ||||||
subList a b xs = if a > b then [] else | ||||||
drop a . take (b + 1) $ xs | ||||||
|
||||||
{- | | ||||||
=⚔️= Task 4 | ||||||
|
@@ -348,9 +360,10 @@ 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 :: [a] -> [a] | ||||||
firstHalf l = take len l | ||||||
where len = (length l) `div` 2 | ||||||
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. Neat usage of
Suggested change
|
||||||
|
||||||
{- | | ||||||
=🛡= Pattern matching | ||||||
|
@@ -501,7 +514,10 @@ True | |||||
>>> isThird42 [42, 42, 0, 42] | ||||||
False | ||||||
-} | ||||||
isThird42 = error "isThird42: Not implemented!" | ||||||
|
||||||
isThird42 :: Integral a => [a] -> Bool | ||||||
isThird42 (_ : _ : x : _) = x == 42 | ||||||
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. You don't need to compare
Suggested change
|
||||||
isThird42 _ = False | ||||||
|
||||||
|
||||||
{- | | ||||||
|
@@ -605,9 +621,10 @@ Implement a function that duplicates each element of the list | |||||
"aabbaacc" | ||||||
|
||||||
-} | ||||||
duplicate :: [a] -> [a] | ||||||
duplicate = error "duplicate: Not implemented!" | ||||||
-- Couldn't figure out how to do it with a pattern match? Not sure if this is right | ||||||
|
||||||
duplicate :: [a] -> [a] | ||||||
duplicate = concatMap (replicate 2) | ||||||
|
||||||
{- | | ||||||
=⚔️= Task 7 | ||||||
|
@@ -621,7 +638,11 @@ 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 (x : y ) = x : go y | ||||||
where go (y:x) = takeEven x | ||||||
go [] = [] | ||||||
takeEven [] = [] | ||||||
|
||||||
{- | | ||||||
=🛡= Higher-order functions | ||||||
|
@@ -727,8 +748,9 @@ value of the element itself | |||||
|
||||||
🕯 HINT: Use combination of 'map' and 'replicate' | ||||||
-} | ||||||
|
||||||
smartReplicate :: [Int] -> [Int] | ||||||
smartReplicate l = error "smartReplicate: Not implemented!" | ||||||
smartReplicate l = concatMap (\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. Now, after you've mastered eta-reduction, you can apply such a technique to this function as well 🙂 |
||||||
|
||||||
{- | | ||||||
=⚔️= Task 9 | ||||||
|
@@ -741,7 +763,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 :: Integral a => a -> [[a]] -> [[a]] | ||||||
contains n xs = filter (\ys -> n `elem` ys) xs | ||||||
|
||||||
|
||||||
{- | | ||||||
|
@@ -780,14 +803,16 @@ nextInt = add 1 | |||||
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 :: (Num a, Ord a) => a -> [a] -> [a] | ||||||
listElementsLessThan x = filter (< x) | ||||||
|
||||||
-- Can you eta-reduce this one??? | ||||||
pairMul xs ys = zipWith (*) xs ys | ||||||
pairMul :: Num a => [a] -> [a] -> [a] | ||||||
pairMul xs = (zipWith (*) xs) | ||||||
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. You can go even further and eta reduce
Suggested change
|
||||||
|
||||||
{- | | ||||||
=🛡= Lazy evaluation | ||||||
|
@@ -842,7 +867,9 @@ list. | |||||
|
||||||
🕯 HINT: Use the 'cycle' function | ||||||
-} | ||||||
rotate = error "rotate: Not implemented!" | ||||||
rotate n xs = if (n /= (abs n)) then | ||||||
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. Is this a check on negative number? |
||||||
[] | ||||||
else take (length xs) $ drop n $ (cycle xs) | ||||||
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. Unfortunately, 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. Also, you can optimise the solution by dropping only |
||||||
|
||||||
{- | | ||||||
=💣= Task 12* | ||||||
|
@@ -858,8 +885,10 @@ 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:xs) = rewind xs ++ [x] | ||||||
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. Your solution is correct! However, it is slow. In lists, it is quite slow to add anything at the end of the list. That is why it is always better to rewrite it with the That is why a more efficient solution is with the accumulator and the recursive function that will do the addition at the start of the list which is instant! You can read a bit more about the |
||||||
rewind [] = [] | ||||||
|
||||||
{- | ||||||
You did it! Now it is time to open pull request with your changes | ||||||
|
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.
Your implementation is correct when the right bound is lower than the left. But I think you also check on negative bounds here too 👌🏼