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 Tasks #557

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Chapter 1 Tasks #557

wants to merge 4 commits into from

Conversation

naprof007
Copy link

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

@naprof007 naprof007 requested a review from vrom911 as a code owner March 23, 2023 23:42
@naprof007
Copy link
Author

naprof007 commented Mar 24, 2023

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

I reinstalled ghc and it helped. Fixed some issues in last commit.

@naprof007
Copy link
Author

@vrom911
Is that right that for the 4th chapter function addM there is a test case:

andM (Just False) Nothing shouldBe Just False

Should not it be Nothing instead of Just False?

Could you review 3 chapters done for now, please? :)

Copy link
Member

@vrom911 vrom911 left a 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
Copy link
Member

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 🙂

Comment on lines +579 to +580
| c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' = True
| otherwise = False
Copy link
Member

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:

Suggested change
| c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' = True
| otherwise = False
= c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'

Copy link
Author

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:

Oh, yeah :) I've just forgot it for a moment))

Comment on lines +646 to +647
a = an `mod` 10
b = (an `div` 10) `mod` 10
Copy link
Member

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 🙂

Comment on lines +654 to +656
takeEven [] = []
takeEven [x] = [x]
takeEven (x:_:xs) = x : takeEven xs
Copy link
Member

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)
Copy link
Member

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))
Copy link
Member

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 🙂

Comment on lines +901 to +903
rewind l = rewind' [] l where
rewind' reversed [] = reversed
rewind' reversed (x:xs) = rewind' (x : reversed) xs
Copy link
Member

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
Copy link
Member

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 👍🏼

Comment on lines +642 to +644
concatList Empty xs = xs
concatList xs Empty = xs
concatList xs (Cons y ys) = concatList (Cons y xs) ys
Copy link
Member

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
Copy link
Member

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.

Copy link
Author

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.

Copy link
Member

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

Copy link
Author

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants