Skip to content
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 complete!! :D #539

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 53 additions & 29 deletions src/Chapter1.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Happy to see you here, on the way to the wonderful Functional Programming land
with Haskell! Fight the fierce Monad Dragon and save the globe from despicable
runtime exceptions!


We appreciate your curiosity and will try to provide you with all the necessary
equipment for your training before the battle in the real FP world. Learning
Functional Programming can be challenging. But we designed this training to be
Expand Down Expand Up @@ -70,6 +69,7 @@ Each Haskell module starts with the "module <MODULE_NAME> where" line.
Modules should have the same name as the corresponding file with
the `.hs` extension.
-}

module Chapter1 where

{- |
Expand Down Expand Up @@ -115,7 +115,7 @@ immediately see what types will be inferred.
-}


{-
{-
Haskell is a __compiled__ language. In the illustration below, you can see the
overall picture of the process from your code to the binary of the written
program:
Expand Down Expand Up @@ -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 p => p

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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)


Expand All @@ -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
Expand Down Expand Up @@ -490,7 +492,9 @@ 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your implementation is almost correct 🆗
Unfortunately, it returns negative numbers on negative inputs because of how mod works. Sometimes corner cases can be tricky to spot and fix...



{- |
Expand Down Expand Up @@ -519,8 +523,9 @@ branches because it is an expression and it must always return some value.
👩‍🔬 Due to lazy evaluation in Haskell, only the expression from the branch
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 y > abs x then x else y


{- |
Expand Down Expand Up @@ -554,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 :: Int -> Int -> Int -> Int
mid x y z
| (x > y && x < z) || (x < y && x > z) = x
| (y > x && y < z) || (y < x && y > z) = y
| (z > y && z < x) || (z < y && z > x) = z
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we mentioned, the compiler in Haskell is very attentive to the exhaustive pattern-matching. And here it would warn you that Pattern matching is not exhaustive, as the guards have quite complicated logic, and the compiler won't be able to prove that it covers all the cases.

Because of that, you will need to add another guard – | otherwise = ..., to tell the compiler, that your pattern matching is exhaustive 🙂

In this case, it would be enough to replace the last condition check with otherwise, as we know that this is the only possibility left here 🙂

Suggested change
| (z > y && z < x) || (z < y && z > x) = z
| otherwise = z

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh right, i forgot thah jaja, i send my changes in my PR on the chapter 2, thank you so much :)


{- |
=⚔️= Task 8
Expand All @@ -568,8 +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

{- |
== Local variables and functions
Expand Down Expand Up @@ -631,8 +647,16 @@ 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 :: Int -> Int
sumLast2 n = modDigits n
where
modDigits :: Int -> Int
modDigits x
| x < 10 = x
| x < 100 = mod x 10
| x < 1000 = mod x 100
| otherwise = mod x 1000
Comment on lines +656 to +659
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are on the right way here! You see that there is the pattern in all of this steps.
Instead of manual few steps here, you can continue doing mod x 10 here until x would be smaller than 10 :)
For that you can use recursiuon (call the same function over and over again from the body of the function itself 👌🏼


sumLast2 n = error "sumLast2: Not implemented!"


{- |
Expand Down