From 9288dfba6c673373f17c2ea6cfc6db3ce3ad59dc Mon Sep 17 00:00:00 2001
From: naprof007 <alexprof2003@inbox.ru>
Date: Fri, 24 Mar 2023 02:31:31 +0300
Subject: [PATCH 1/4] Chapter 1 Tasks

---
 src/Chapter1.hs | 69 +++++++++++++++++++++++++++++--------------------
 1 file changed, 41 insertions(+), 28 deletions(-)

diff --git a/src/Chapter1.hs b/src/Chapter1.hs
index 406deeaca..a9518f08e 100644
--- a/src/Chapter1.hs
+++ b/src/Chapter1.hs
@@ -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 = 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
 
 
 {- |
@@ -632,7 +641,10 @@ 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 = n `mod` 10
+  b = (n `div` 10) `mod` 10
 
 
 {- |
@@ -653,7 +665,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 = if n < 10 then n else firstDigit (n `div` 10)
 
 
 {-

From cd869ed98799f8ee413a9988f0498b3805c2133a Mon Sep 17 00:00:00 2001
From: naprof007 <alexprof2003@inbox.ru>
Date: Fri, 24 Mar 2023 05:36:56 +0300
Subject: [PATCH 2/4] Chapter 1 Solutions fixes

---
 src/Chapter1.hs | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/Chapter1.hs b/src/Chapter1.hs
index a9518f08e..a34fc7abd 100644
--- a/src/Chapter1.hs
+++ b/src/Chapter1.hs
@@ -304,7 +304,7 @@ expressions in GHCi
 3
 
 >>> 10 - 15
-5
+-5
 
 >>> 10 - (-5)  -- negative constants require ()
 15
@@ -492,7 +492,7 @@ Implement a function that returns the last digit of a given number.
 -}
 -- DON'T FORGET TO SPECIFY THE TYPE IN HERE
 lastDigit :: Integral a => a -> a
-lastDigit n = n `mod` 10
+lastDigit n = abs n `mod` 10
 
 
 {- |
@@ -558,9 +558,9 @@ Casual reminder about adding top-level type signatures for all functions :)
 
 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
+    | x <= y && x > z || x >= y && x < z = x
+    | y <= x && y > z || y >= x && y < z = y
+    | otherwise                          = z
 
 {- |
 =⚔️= Task 8
@@ -643,8 +643,9 @@ specifying complex expressions.
 
 sumLast2 :: Integral a => a -> a
 sumLast2 n = b + a where
-  a = n `mod` 10
-  b = (n `div` 10) `mod` 10
+  a = an `mod` 10
+  b = (an `div` 10) `mod` 10
+  an = abs n
 
 
 {- |
@@ -666,7 +667,7 @@ aren't ready for this boss yet!
 -}
 
 firstDigit :: Integral t => t -> t
-firstDigit n = if n < 10 then n else firstDigit (n `div` 10)
+firstDigit n = let an = abs n in if an < 10 then an else firstDigit (an `div` 10)
 
 
 {-

From 191c89f875fa599c972098eecf0dd7befbeda8cf Mon Sep 17 00:00:00 2001
From: naprof007 <alexprof2003@inbox.ru>
Date: Fri, 24 Mar 2023 07:17:37 +0300
Subject: [PATCH 3/4] Chapter 2 Solution

---
 src/Chapter2.hs | 66 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 54 insertions(+), 12 deletions(-)

diff --git a/src/Chapter2.hs b/src/Chapter2.hs
index b98ceaf7d..f9b3d9f2a 100644
--- a/src/Chapter2.hs
+++ b/src/Chapter2.hs
@@ -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
 
 {- |
 =🛡= 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)
 
 {- |
 =⚔️= 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 (*)
 
 {- |
 =🛡= 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))
 
 {- |
 =💣= 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
 
 
 {-

From b014b14e541c1b921112fc92607010a464777f0f Mon Sep 17 00:00:00 2001
From: naprof007 <alexprof2003@inbox.ru>
Date: Sat, 25 Mar 2023 03:54:46 +0300
Subject: [PATCH 4/4] Chapter 4 Solutions

---
 src/Chapter4.hs | 43 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)

diff --git a/src/Chapter4.hs b/src/Chapter4.hs
index caec5a95d..0c4f7b59b 100644
--- a/src/Chapter4.hs
+++ b/src/Chapter4.hs
@@ -113,22 +113,30 @@ As always, try to guess the output first! And don't forget to insert
 the output in here:
 
 >>> :k Char
+Char :: *
 
 >>> :k Bool
+Bool :: *
 
 >>> :k [Int]
+[Int] :: *
 
 >>> :k []
+[] :: * -> *
 
 >>> :k (->)
+(->) :: * -> * -> *
 
 >>> :k Either
+Either :: * -> * -> *
 
 >>> data Trinity a b c = MkTrinity a b c
 >>> :k Trinity
+Trinity :: * -> * -> * -> *
 
 >>> data IntBox f = MkIntBox (f Int)
 >>> :k IntBox
+IntBox :: (* -> *) -> *
 
 -}
 
@@ -292,7 +300,8 @@ values and apply them to the type level?
 -}
 instance Functor (Secret e) where
     fmap :: (a -> b) -> Secret e a -> Secret e b
-    fmap = error "fmap for Box: not implemented!"
+    fmap _ (Trap e) = Trap e
+    fmap f (Reward x) = Reward (f x)
 
 {- |
 =⚔️= Task 3
@@ -306,6 +315,10 @@ data List a
     = Empty
     | Cons a (List a)
 
+instance Functor List where
+    fmap _ Empty = Empty
+    fmap f (Cons x xs) = Cons (f x) (fmap f xs)
+
 {- |
 =🛡= Applicative
 
@@ -471,10 +484,12 @@ Implement the Applicative instance for our 'Secret' data type from before.
 -}
 instance Applicative (Secret e) where
     pure :: a -> Secret e a
-    pure = error "pure Secret: Not implemented!"
+    pure = Reward
 
     (<*>) :: Secret e (a -> b) -> Secret e a -> Secret e b
-    (<*>) = error "(<*>) Secret: Not implemented!"
+    (Trap f) <*> _ = Trap f
+    _ <*> (Trap x) = Trap x
+    Reward f <*> x = fmap f x
 
 {- |
 =⚔️= Task 5
@@ -489,6 +504,16 @@ Implement the 'Applicative' instance for our 'List' type.
 -}
 
 
+instance Applicative List where
+  pure x = Cons x Empty
+  (<*>) :: List (a -> b) -> List a -> List b
+  Empty <*> _ = Empty
+  _ <*> Empty = Empty
+  Cons f fs <*> x = fmap f x `concatList` (fs <*> x) where
+      concatList Empty xs = xs
+      concatList xs Empty = xs
+      concatList xs (Cons y ys) = concatList (Cons y xs) ys
+
 {- |
 =🛡= Monad
 
@@ -599,7 +624,8 @@ Implement the 'Monad' instance for our 'Secret' type.
 -}
 instance Monad (Secret e) where
     (>>=) :: Secret e a -> (a -> Secret e b) -> Secret e b
-    (>>=) = error "bind Secret: Not implemented!"
+    Trap x >>= _ = Trap x
+    Reward x >>= f = f x
 
 {- |
 =⚔️= Task 7
@@ -610,6 +636,13 @@ Implement the 'Monad' instance for our lists.
   maybe a few) to flatten lists of lists to a single list.
 -}
 
+instance Monad List where
+    Empty >>= _ = Empty
+    Cons x xs >>= f = f x `concatList` (Cons x xs >>= f) where
+        concatList Empty xs = xs
+        concatList xs Empty = xs
+        concatList xs (Cons y ys) = concatList (Cons y xs) ys
+
 
 {- |
 =💣= Task 8*: Before the Final Boss
@@ -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
 
 {- |
 =🐉= Task 9*: Final Dungeon Boss