-
-
Notifications
You must be signed in to change notification settings - Fork 843
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
Conversation
I reinstalled ghc and it helped. Fixed some issues in last commit. |
@vrom911 andM (Just False) Nothing Should not it be Nothing instead of Just False? Could you review 3 chapters done for now, please? :) |
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.
Fantastic job! I left some comments, but you did incredibly well! 👏🏼
@@ -429,6 +429,7 @@ task is to specify the type of this function. | |||
49 | |||
-} | |||
|
|||
squareSum :: Num a => a -> a -> a |
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 🙂
| c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' = True | ||
| otherwise = False |
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.
Yes, this is right!
As ||
operator already returns the Bool
, you can also skip the cases and use just it:
| c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' = True | |
| otherwise = False | |
= c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' |
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.
Yes, this is right!
As
||
operator already returns theBool
, you can also skip the cases and use just it:
Oh, yeah :) I've just forgot it for a moment))
a = an `mod` 10 | ||
b = (an `div` 10) `mod` 10 |
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.
That is a wonderful solution! 👏🏼 You correctly noticed that it is the div
and mod
, cool 😎
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 divMod
function, that actually combines inside both div
and mod
. And this is exactly what you use!.
So you could write it this way:
(x, y) = divMod m 10
You can see how we could pattern match on the pair 🙂
takeEven [] = [] | ||
takeEven [x] = [x] | ||
takeEven (x:_:xs) = x : takeEven xs |
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.
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! 👏🏼
@@ -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 comment
The reason will be displayed to describe this comment to others. Learn more.
Great! 👍🏼
If you want to write this function even more elegantly, you can use the standard function concatMap
which is a combination of concat
and map
as the name suggests 🙂
After that, you could notice, that you would be able to eta-reduce on the last argument :)
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
You can optimise it a little bit by using mod n (length l)
as in this case you won't overgo if n
is too huge 🙂
rewind l = rewind' [] l where | ||
rewind' reversed [] = reversed | ||
rewind' reversed (x:xs) = rewind' (x : reversed) xs |
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.
Fantastic solution 🎉
Nothe, that there is no need to pattern match on the empty list in the rewind
itself as you check this case in rewind'
anyway, so you can get rid of this case 🙂
|
||
(<*>) :: Secret e (a -> b) -> Secret e a -> Secret e b | ||
(<*>) = error "(<*>) Secret: Not implemented!" | ||
(Trap f) <*> _ = Trap f | ||
_ <*> (Trap x) = Trap x |
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.
This case is unnecessary and should be covered by the next case 👍🏼
concatList Empty xs = xs | ||
concatList xs Empty = xs | ||
concatList xs (Cons y ys) = concatList (Cons y xs) ys |
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.
You can put this function on the global level as it is used in two places already 👌🏼
@@ -628,7 +661,7 @@ Can you implement a monad version of AND, polymorphic over any monad? | |||
🕯 HINT: Use "(>>=)", "pure" and anonymous function | |||
-} | |||
andM :: (Monad m) => m Bool -> m Bool -> m Bool | |||
andM = error "andM: Not implemented!" | |||
andM mx my = mx >>= \x -> my >>= \y -> pure $ x && y |
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.
Regarding your question, in the test case Just False
is there on purpose.
The ordinary &&
if lazy on the second argument. Meaning that if it meets False
as the first argument, there is no need to calculate another arg. In andM
we would like to keep the same behaviour, so the
Just False `andM` _
should be Just False
🙂
If you don't use the >>=
operator, then the Monad
constraint is too strong, and it is enough to specify only Applicative
. However, with Applicative
you are not able to implement a lazier version of andM
.
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.
For my code this test fails. How can I change code to pass this test case? Don't understand yet.
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.
Sure, no problem! All you need to do is to first check on the first value and stop lazily in case it is False
. The code could look. like this:
andM ma mb = ma >>= \a -> if a then mb else pure False
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.
I see. Thank you for your help and review :)
Could you suggest what can be done next to improve Haskell skills?
Solutions for Chapter 1
cc @vrom911
Hi. I've solved tasks in chapter 1, but can't run tests for some reasons: (could you help with that?)
make test-chapter1
cabal test doctest-chapter1 --enable-tests --test-show-details=direct
Resolving dependencies...
Error: cabal.exe: Could not resolve dependencies:
[__0] trying: learn4haskell-0.0.0.0 (user goal)
[__1] next goal: base (dependency of learn4haskell)
[__1] rejecting: base-4.17.0.0/installed-4.17.0.0 (conflict: learn4haskell =>
base>=4.14.0.0 && <4.17)
[__1] skipping: base-4.18.0.0, base-4.17.0.0 (has the same characteristics
that caused the previous version to fail: excluded by constraint '>=4.14.0.0
&& <4.17' from 'learn4haskell')
[__1] rejecting: base-4.16.4.0, base-4.16.3.0, base-4.16.2.0, base-4.16.1.0,
base-4.16.0.0, base-4.15.1.0, base-4.15.0.0, base-4.14.3.0, base-4.14.2.0,
base-4.14.1.0, base-4.14.0.0, base-4.13.0.0, base-4.12.0.0, base-4.11.1.0,
base-4.11.0.0, base-4.10.1.0, base-4.10.0.0, base-4.9.1.0, base-4.9.0.0,
base-4.8.2.0, base-4.8.1.0, base-4.8.0.0, base-4.7.0.2, base-4.7.0.1,
base-4.7.0.0, base-4.6.0.1, base-4.6.0.0, base-4.5.1.0, base-4.5.0.0,
base-4.4.1.0, base-4.4.0.0, base-4.3.1.0, base-4.3.0.0, base-4.2.0.2,
base-4.2.0.1, base-4.2.0.0, base-4.1.0.0, base-4.0.0.0, base-3.0.3.2,
base-3.0.3.1 (constraint from non-upgradeable package requires installed
instance)
[__1] fail (backjumping, conflict set: base, learn4haskell)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: base, learn4haskell
make: *** [Makefile:11: test-chapter1] Error 1