Complete chapters 5-9

master
Gaël Depreeuw 7 years ago
parent d7b08372e7
commit f882643891
  1. 6
      05-types/5.3-type-matching.md
  2. 11
      05-types/5.4-type-arguments.md
  3. 7
      05-types/5.5-parametricity.md
  4. 6
      05-types/5.6-apply-yourself.md
  5. 47
      05-types/5.8-chapter-excercises.md
  6. 10
      05-types/src/arith3broken.hs
  7. 42
      05-types/src/defineFunc.hs
  8. 22
      05-types/src/sing.hs
  9. 52
      05-types/src/typekwondo.hs
  10. 32
      06-typeclasses/6.14-chapter-exercises.md
  11. 2
      06-typeclasses/6.6-eq-instances.md
  12. 3
      06-typeclasses/6.6-tuple-experiment.md
  13. 5
      06-typeclasses/6.8-will-they-work.md
  14. 47
      06-typeclasses/src/eqinstances.hs
  15. 33
      06-typeclasses/src/typecheck.hs
  16. 13
      06-typeclasses/src/typekwondo.hs
  17. 11
      07-more-functional-patterns/7.11-chapter-exercises.md
  18. 16
      07-more-functional-patterns/7.3-grab-bag.md
  19. 9
      07-more-functional-patterns/7.4-variety-pack.md
  20. 2
      07-more-functional-patterns/7.5-case-practise.md
  21. 14
      07-more-functional-patterns/7.6-artful-dodgy.md
  22. 24
      07-more-functional-patterns/7.7-guard-duty.md
  23. 10
      07-more-functional-patterns/src/artfuldodgy.hs
  24. 23
      07-more-functional-patterns/src/casepractise.hs
  25. 43
      07-more-functional-patterns/src/writecode.hs
  26. 15
      08-recursion/8.2-intermission.md
  27. 40
      08-recursion/8.6-chapter-exercises.md
  28. 19
      08-recursion/src/dividedby.hs
  29. 6
      08-recursion/src/mccarthy91.hs
  30. 38
      08-recursion/src/recursion.hs
  31. 25
      08-recursion/src/wordnumber.hs
  32. 2
      09-lists/9.10-filtering.md
  33. 2
      09-lists/9.11-zipping-exercises.md
  34. 9
      09-lists/9.12-chapter-exercises.md
  35. 2
      09-lists/9.5-enumfromto.md
  36. 9
      09-lists/9.6-the-fearful-symmetry.md
  37. 4
      09-lists/9.7-comprehend-thy-lists.md
  38. 2
      09-lists/9.7-square-cube.md
  39. 21
      09-lists/9.8-bottom-madness.md
  40. 10
      09-lists/9.9-more-bottoms.md
  41. 25
      09-lists/src/char.hs
  42. 27
      09-lists/src/cipher.hs
  43. 42
      09-lists/src/enumfromto.hs
  44. 18
      09-lists/src/filtering.hs
  45. 21
      09-lists/src/poemlines.hs
  46. 25
      09-lists/src/split.hs
  47. 18
      09-lists/src/squarecube.hs
  48. 67
      09-lists/src/standards.hs
  49. 7
      09-lists/src/words.hs
  50. 14
      09-lists/src/zipping.hs

@ -0,0 +1,6 @@
# Exercises: Type Matching
1. (c) `not :: Bool -> Bool`
2. (d) `length :: [a] -> Int`
3. (b) `concat :: [[a]] -> [a]`
4. (a) `head :: [a] -> a`
5. (e) `(<) :: Ord a => a -> a -> Bool`

@ -0,0 +1,11 @@
# Exercises: Type Arguments
1. (a) `Char -> Char -> Char`
2. (d) `Char`
3. (d) `Num b => b`
4. (c) `Double`
5. (a) `[Char]`
6. (e) `Eq b => b -> [Char]`
7. (d) `(Ord a, Num a) => a`, `a` is also of typeclass `Num` due to (`1 :: Num`)
8. (a) `(Ord a, Num a) => a`
9. (c) `Integer`

@ -0,0 +1,7 @@
# Exercises: Parametricity
1. As said this is impossible. A function which takes any type and returns that same type can't be anything else. As soon as you choose something else, you pose limitations on the type. E.g. `square x = x * x` requires that `x` can be applied to `(*)`, which means it has to be of type `Num` at least.\
2. The only possibilies are to return either the first or the second argument.
1. `fst' a1 a2 = a1`
2. `snd' a1 a2 = a2`
3. Here there is only one possiblity: `snd'' a b = b`.

@ -0,0 +1,6 @@
# Exercise: Apply Yourself
1. `myConcat :: [Char] -> [Char] -> [Char]`. The second argument to `(++)` is a `[Char]` and so all types need to be `[Char]`.
2. `myMult :: Fractional a => a -> a`. The `(/)` requires the `Fractional` typeclass (which is a subset of the `Num` class.)
3. `myTake :: Int -> [Char] -> [Char]`. Same reason a (1)
4. `myCom :: Int -> Bool`. Second argument of `(<)` is `Int`, which inherits the `Ord` typeclass so we no longer need to specify it.
5. `myAlph :: Char -> Bool`.

@ -0,0 +1,47 @@
# Chapter Excercises
## Multiple choice
1. (c)
2. (a)
3. (b)
4. (c)
## Determine the type
1.
1. `Num a => a`
2. `Num a => (a, [Char])`
3. `(Integer, [Char])`
4. `Bool`
5. `Int`
6. `Bool`
2. `Num a => a`
3. `Num a => a -> a`
4. `Fractional a => a`
5. `[Char]`
## Does it compile?
1. The definition of `wahoo` tries to apply a `Num` to another `Num` which does not work. Either change `bigNum` to take an argument (`bigNum x = (^) 5 $ x ; wahoo = bigNum $ 10`) or fix `wahoo`, e.g. `wahoo = bigNum`
2.Nothing wrong here.
3. `c` tries to apply `5` to `b = 5` which does not work. It's also expected to take an argument in the definition of `d = c 200`. A fix could thus be: `c = a 10`.
4. `c` is not defined for the definition of `b`.
## Type variable or specific type constructor?
1. /
2. `zed` is fully polymorphic, `Zed` and `Blah` are concrete.
3. `a` is fully polymorphic, `b` is constrained and `C` is concrete.
4. `f` and `g` are fully polymorphic and `C` is concrete.
## Write a type signature
1. `functionH :: [a] -> a`
2. `functionC :: (Ord a) => a -> a -> Bool`
3. `functionS :: (a, b) -> b`
## Given a type, write the function
see src/defineFunc.hs
## Fix it
1. see src/sing.hs
2. see src/sing.hs
3. see src/arith3broken.hs
## Type-Kwon-Do
see src/typekwondo.hs

@ -0,0 +1,10 @@
module Arith3Broken where
main :: IO ()
-- Main should be main
main = do
print (1 + 2) -- added braces
putStrLn "10" -- must be String
print (negate (-1)) -- or negate 1
print ((+) 0 blah)
where blah = negate 1

@ -0,0 +1,42 @@
module DefineFunc where
-- 1
i :: a -> a
i x = x;
-- 2
c :: a -> b -> a
c x _ = x
-- 3
c'' :: b -> a -> b
c'' x _ = x
-- Yes they are the same thing
-- 4
c' :: a -> b -> b
c' _ y = y
-- 5
r :: [a] -> [a]
--r (_:xs) = xs
r (x:xs) = xs ++ [x]
-- any many other options...
-- 6
co :: (b -> c) -> (a -> b) -> a -> c
co = (.)
-- co bToC aToB a = bToC (aToB a)
-- co f g a = (f . g) a
-- co f g = (f . g)
-- These are all the same.
-- 7
a :: (a -> c) -> a -> a
a _ x = x
-- 8
a' :: (a -> b) -> a -> b
a' = ($)
-- a f x = f x
-- a f = f

@ -0,0 +1,22 @@
module Sing where
-- ++ should be ->
fstString :: [Char] -> [Char]
fstString x = x ++ " in the rain"
-- Char should be [Char]
sndString :: [Char] -> [Char]
sndString x = x ++ " over the rainbow"
-- added type signature
-- y should be 'Somewhere'
sing :: [Char]
sing = if (x > y) then fstString x else sndString y
where x = "Singin"
y = "Somewhere"
-- 2
singOther :: [Char]
singOther = if (x <= y) then fstString x else sndString y
where x = "Singin"
y = "Somewhere"

@ -0,0 +1,52 @@
module TypeKwonDo where
-- 1
f :: Int -> String
f = undefined
g :: String -> Char
g = undefined
h :: Int -> Char
h = g . f
-- 2
data A
data B
data C
q :: A -> B
q = undefined
w :: B -> C
w = undefined
e :: A -> C
e = w . q
-- 3
data X
data Y
data Z
xz :: X -> Z
xz = undefined
yz :: Y -> Z
yz = undefined
xform :: (X, Y) -> (Z, Z)
xform (x, y) = (xz x, yz y)
-- 4
munge :: (x -> y)
-> (y -> (w, z))
-> x
-> w
munge f1 f2 = fst . f2 . f1
--munge f1 f2 x = fst $ (f2 . f1) x
-- (f2 . f1) :: x -> (w,z)
-- munge f1 f2 = fst $ (f2 . f1)
-- doesn't work because you apply fst to a function and it
-- expects a tuple. (f2 . f1) needs to be applied to an argument to get the
-- tuple on which fst can operate.

@ -0,0 +1,32 @@
# Chapter Excercises
## Multiple choice
1. (c)
2. (b)
3. (a)
4. (c)
5. (a)
## Does it typecheck?
see src/typecheck.hs
## Given a datatype declaration, what can we do?
1. Will not type check. `"chases"` is a `String` not a `Rocks` and `True` is of type `Bool`, not `Yeah`
2. Will typecheck.
3. Will typecheck.
4. Will not typecheck, because `Papu` is not an instance of `Ord`
## Match the types
1. Can't be substituted
2. Can't be substituted
3. Can be substituted
4. Can be substituted
5. Can be substituted
6. Can be substituted
7. Can't be substituted
8. Can't be substituted
9. Can be substituted
10. Can be substituted
11. Can't be substituted
## Type-Kwon-Do Two: Electric Typealoo
see src/typekwondo.hs

@ -0,0 +1,2 @@
# Exercises: Eq Instances
see src/eqinstances.hs

@ -0,0 +1,3 @@
# Exercises: Tuple Experiment
`quotRem` and `divMod` return a tuple contain both the results of `(quot, rem)` and `(div, mod)` respectively. E.g. `quotRem 3 5` would return `(0, 3)`

@ -0,0 +1,5 @@
# Exercises: Will They Work?
1. This will work. It will return `5 :: Int`
2. This will also work. It will return `LT`
3. This won't work as the arguments are different types.
4. This will work and will return `False`

@ -0,0 +1,47 @@
module EqInstances where
-- 1
data TisAnInteger = TisAn Integer
instance Eq TisAnInteger where
TisAn x == TisAn y = x == y
-- 2
data TwoIntegers = Two Integer Integer
instance Eq TwoIntegers where
Two x1 x2 == Two y1 y2 =
(x1 == y1) && (x2 == y2)
-- 3
data StringOrInt =
TisAnInt Int
| TisAString String
instance Eq StringOrInt where
TisAnInt x == TisAnInt y = x == y
TisAString s1 == TisAString s2 = s1 == s2
_ == _ = False
-- 4
data Pair a = Pair a a
instance Eq a => Eq (Pair a) where
(==) (Pair a1 a2) (Pair b1 b2) =
(a1 == b1) && (a2 == b2)
-- 5
data Tuple a b = Tuple a b
instance (Eq a, Eq b) => Eq (Tuple a b) where
(==) (Tuple a1 b1) (Tuple a2 b2) =
(a1 == a2) && (b1 == b2)
-- 6
data Which a = ThisOne a | ThatOne a
instance Eq a => Eq (Which a) where
(==) (ThisOne a) (ThisOne a') = a == a'
(==) (ThatOne a) (ThatOne a') = a == a'
(==) _ _ = False
-- 7
data EitherOr a b = Hello a | Goodbye b
instance (Eq a, Eq b) => Eq (EitherOr a b) where
(==) (Hello a) (Hello a') = a == a'
(==) (Goodbye b) (Goodbye b') = b == b'
(==) _ _ = False

@ -0,0 +1,33 @@
module TypeCheck where
-- Does it Type Check ?
-- 1 Does not typecheck. Add `deriving Show`
data Person = Person Bool deriving Show
printPerson :: Person -> IO ()
printPerson person = putStrLn (show person)
-- 2 Does not typecheck. Add `deriving Eq`
data Mood = Blah | Woot deriving (Show, Eq)
settleDown :: Mood -> Mood
settleDown x = if x == Woot then Blah else x
-- 3
-- a. Mood values
-- b. Doesn't typecheck as it expects a `Mood` but gets a `Num`
-- c. Won't compile as Mood is not an instance of Ord
-- 4 This typecheckes.
type Subject = String
type Verb = String
type Object = String
data Sentence = Sentence Subject Verb Object deriving (Show, Eq)
s1 :: Object -> Sentence
s1 = Sentence "dogs" "drool"
s2 :: Sentence
s2 = Sentence "Julie" "loves" "dogs"

@ -0,0 +1,13 @@
module TypeKwonDo where
-- 1
chk :: Eq b => (a -> b) -> a -> b -> Bool
chk f a = (==) (f a)
-- 2
arith :: Num b
=> (a -> b)
-> Integer
-> a
-> b
arith f i a = (f a) + (fromInteger i)

@ -0,0 +1,11 @@
# Chapter Exercises
## Multiple Choice
1. (d)
2. (b)
3. (d)
4. (b)
5. (a)
## Let's write code
see src/writecode.hs

@ -0,0 +1,16 @@
# Exercises: Grab Bag
## Exercise 1
They are all equivalent.
## Exercise 2
(d)
## Exercise 3
### addOneIfOdd
`f = \n -> n + 1`
### addFive
`addFive = \x -> \y -> (if (x > y) then y else x) + 5`
### mflip
`mflip f x y = f y x`

@ -0,0 +1,9 @@
# Exercises: Variety Pack
## Exercise 1
1. The type of k is `(a,b) -> a`
2. The type of k2 is `[Char]` It is different from k1 and k3.
3. k3
## Exercise 2
`f (a,_,c) (d,_,f) = ((a,d), (c,f))`

@ -0,0 +1,2 @@
#Exercises: Case Practise
see src/casepractise.hs

@ -0,0 +1,14 @@
# Exercise: Artful Dodgy
see src/artfuldodgy.hs
1. 1
2. 11
3. 22
4. 21
5. 12
6. 11
7. 21
8. 21
9. 22
10. 31
11. 23

@ -0,0 +1,24 @@
# Exercises: Guard Duty
## Exercise 1
If you start with the `otherwise` statement, all grades will be F's.
## Exercise 2
It will still work, but the result won't be as expected. E.g. if you move `| y >= 0.9 = 'A'` below the B grade, then any grade of 80 or higher will be a B, because `0.9 >= 0.8` is true and thus it matches with the grade for B.
## Exercise 3
(b)
## Exercise 4
`[a]`
## Exercise 5
`pal :: [a] -> Bool`
## Exercise 6
(c)
## Exercise 7
`Ord a => a`
## Exercise 8
`numbers :: (Ord a, Num a, Num b) => a -> b`

@ -0,0 +1,10 @@
module ArtfulDodgy where
dodgy :: Num a => a -> a -> a
dodgy x y = x + y * 10
oneIsOne :: Num a => a -> a
oneIsOne = dodgy 1
oneIsTwo :: Num a => a -> a
oneIsTwo = (flip dodgy) 2

@ -0,0 +1,23 @@
module CasePractise where
-- 1
functionC :: Ord a => a -> a -> a
functionC x y =
case (x > y) of
True -> x
False -> y
-- 2
ifEvenAdd2 :: Integral a => a -> a
ifEvenAdd2 n =
case even n of
True -> n + 2
False -> n
-- 3
nums :: (Ord a, Num a) => a -> a
nums x =
case compare x 0 of
LT -> -1
GT -> 1
EQ -> 0

@ -0,0 +1,43 @@
module WriteCode where
-- 1a
tensDigit :: Integral a => a -> a
tensDigit = snd . (flip divMod) 10
-- 1b This has the same type.
-- 1c
hunsD :: Integral a => a -> a
hunsD = snd . (flip divMod) 100
-- 2
foldBool1 :: a -> a -> Bool -> a
foldBool1 x y b =
case b of
False -> x
True -> y
foldBool2 :: a -> a -> Bool -> a
foldBool2 x y b
| b == False = x
| otherwise = y
-- 3
g :: (a -> b) -> (a, c) -> (b, c)
g f (a, c) = (f a, c)
-- 4
roundTrip :: (Show a, Read a) => a -> a
roundTrip a = read (show a)
main :: IO ()
main = do
print ((roundTrip 4) :: Integer)
print (id 4 :: Integer)
-- 5
roundTrip' :: (Show a, Read a) => a -> a
roundTrip' = read . show
-- 6
roundTrip'' :: (Show a, Read b) => a -> b
roundTrip'' = read . show
-- roundTrip'' 4 :: Integer

@ -0,0 +1,15 @@
# Intermission: Exercise
```
applyTimes 5 (+1) 5
= (+1) (applyTimes 4 (+1) 5)
= (+1) ((+1) (applyTimes 3 (+1) 5))
= (+1) ((+1) ((+1) (applyTimes 2 (+1) 5)))
= (+1) ((+1) ((+1) ((+1) (applyTimes 1 (+1) 5))))
= (+1) ((+1) ((+1) ((+1) ((+1) (applyTimes 0 (+1) 5)))))
= (+1) ((+1) ((+1) ((+1) ((+1) (5)))))
= (+1) ((+1) ((+1) ((+1) (6))))
= (+1) ((+1) ((+1) (7)))
= (+1) ((+1) (8))
= (+1) (9)
= 10
```

@ -0,0 +1,40 @@
# Chapter Exercises
## Review of types
1. `[[Bool]]`
2. (c)
3. (d)
4. (b)
## Reviewing currying
1. `"woops mrow wooho!"`
2. `"1 mrow haha"`
3. `"woops mrow 2 mrow haha"`
4. `"woops mrow blue mrow haha"`
5. `"pink mrow haha mrow green mrow woops mrow blue"`
6. `"are mrow Pugs mrow awesome"`
## Recursion
### Exercise 1
```
dividedBy 15 2
= go 15 2 0
= go 13 2 1
= go 11 2 2
= go 9 2 3
= go 7 2 4
= go 5 2 5
= go 3 2 6
= go 1 2 7
= (7,1)
```
### Exercise 2 & 3
see src/recursion.hs
### Exercise 4
see src/dividedby.hs
### Exercise 5
see src/mccarthy91.hs
## Numbers into words
see src/wordnumber.hs

@ -0,0 +1,19 @@
module DividedBy where
dividedBy :: Integral a => a -> a -> (a, a)
dividedBy num denom = go num denom 0
where go n d count
| n < d = (count, n)
| otherwise = go (n - d) d (count + 1)
-- For this exercise, we'll revert to the Integer -> Integer -> Integer type.
-- This, to be able to use the hint provides which uses Integer
data DividedResult =
Result Integer
| DividedByZero
deriving (Show)
dividedBy' :: Integer -> Integer -> DividedResult
dividedBy' _ 0 = DividedByZero
dividedBy' num denom = -- is actually the same as the regular function.
Result . toInteger . fst $ dividedBy num denom

@ -0,0 +1,6 @@
module McCarthy91 where
mc91 :: (Integral a) => a -> a
mc91 n
| n > 100 = n - 10
| otherwise = mc91 . mc91 $ n + 11

@ -0,0 +1,38 @@
module Recursion where
-- 2
recsum :: (Eq a, Num a) => a -> a
recsum 1 = 1
recsum n = n + (recsum (n -1))
-- The above function does not really work with negative numbers but we can't
-- check for negativity because this would require the Ord typeclass.
-- You can use abs however
recsum' :: (Eq a, Num a) => a -> Maybe a
recsum' n
| isNegative n = Nothing
| n == 0 = Just 0
| otherwise = go (+n) (recsum' (n - 1))
where go f (Just a) = Just (f a)
go _ _ = Nothing
-- Or: | otherwise = fmap (+n) (recsum' (n - 1))
-- 3
myMult :: (Integral a) => a -> a -> a
myMult 0 _ = 0
myMult _ 0 = 0
myMult x y
| y >= 0 = go x y
-- if y is negative we'll just treat y as positive and negate the result.
-- x * (-y) = - (x * y)
| otherwise = negate $ go x $ negate y
where go a 1 = a
go a b = a + (go a (b-1))
-- helper functions
isPositive :: (Eq a, Num a) => a -> Bool
isPositive n =
n == abs n
isNegative :: (Eq a, Num a) => a -> Bool
isNegative = not . isPositive

@ -0,0 +1,25 @@
module WordNumber where
import Data.List (intersperse)
digitToWord :: Int -> String
digitToWord 0 = "zero"
digitToWord 1 = "one"
digitToWord 2 = "two"
digitToWord 3 = "three"
digitToWord 4 = "four"
digitToWord 5 = "five"
digitToWord 6 = "six"
digitToWord 7 = "seven"
digitToWord 8 = "eight"
digitToWord 9 = "nine"
digitToWord _ = ""
digits :: Int -> [Int]
digits n
| d == 0 = [r]
| otherwise = digits d ++ [r]
where (d,r) = divMod (abs n) 10
wordNumber :: Int -> String
wordNumber = concat . intersperse "-" . map digitToWord . digits

@ -0,0 +1,2 @@
# Exercises: Filtering
see src/filtering.hs

@ -0,0 +1,2 @@
# Zipping Exercises
see src/zipping.hs

@ -0,0 +1,9 @@
# Chapter Exercises
## Data.Char
see src/char.hs
## Ciphers
see src/cipher.hs
## Writing your own standard functions
see src/standards.hs

@ -0,0 +1,2 @@
# Exercise: EnumFromTo
see src/enumfromto.hs

@ -0,0 +1,9 @@
# Exercises: The Fearful Symmetry
## Exercise 1
see src/words.hs
## Exercise 2
see src/poemlines.hs
## Exercise 3
see src/split.hs

@ -0,0 +1,4 @@
# Exercises: Comprehend Thy Lists
1. Takes all squares of the even numbers from 1 to 10
2. Combines all pairs of squares from numbers 1 to 10 smaller than 50 and larger than 50.
3. Takes the first 5 items of the previous list. The pairs will first be generated while keeping the x's the same. I.e. `[(1,64),(1,81),(1,100),(4,64),(4,81)]`

@ -0,0 +1,2 @@
# Exercises: Square Cube
see src/squarecube.hs

@ -0,0 +1,21 @@
# Exercises: Bottom Madness
## Will it blow up?
1. Bottom
2. Will return `[1]`
3. Bottom
4. Will return `3`
5. Bottom
6. Will return `[2]`
7. Bottom
8. Will return `[1]`
9. Will return `[1,3]`
10. Bottom
## Intermission: Is it in normal form?
1. NF - No further evaluation possible.
2. WHNF - `:` is a data constructor, but due to the `_` it isn't fully evaluated.
3. Neither - `enumFromTo` is not a data constructor
4. Neither - `length` is not a data constructor
5. Neither - `sum` is not a data constructor
6. Neither - `++` is not a data constructor
7. WHNF - `(,)` is a data constructor, but due to the `_` it is not fully evaluated.

@ -0,0 +1,10 @@
# Exercises: More Bottoms
1. Bottom
2. Will return `2`
3. Bottom
4. `itIsMyster :: [Char] -> [Bool]` replaces every character in the input to `True` if it is a vowel and `False` otherwise.
5. The answers:
1. Squares every value in the list: `[1,4,9,16,26,36,49,64,81,100]`
2. Takes the smallest element of every sub-list: `[1,10,20]`
3. Sums every sub-list: `[15,15,15]`
4. `map (\x -> bool (x) (-x) (x == 3))`

@ -0,0 +1,25 @@
module Char where
import Data.Char
-- 2
filterUpper :: [Char] -> [Char]
filterUpper = filter isUpper
-- 3
upFirst :: [Char] -> [Char]
upFirst [] = []
upFirst (x:xs) = toUpper x : xs
-- 4
upAll :: [Char] -> [Char]
upAll [] = []
upAll (x:xs) = toUpper x : upAll xs
-- 5
getUppedFirst :: String -> Char
getUppedFirst s = toUpper $ head s
-- 6
getUppedFirst' :: String -> Char
getUppedFirst' = toUpper . head

@ -0,0 +1,27 @@
module Cipher where
import Data.Char
-- Chapter 9.12
caesar :: String -> Int -> String
caesar [] _ = []
caesar (x:xs) k
| isAlpha x = go x k ++ caesar xs k
| otherwise = caesar xs k
where go c key = [enc c (+) key]
unCaesar :: String -> Int -> String
unCaesar [] _ = []
unCaesar (x:xs) k
| isAlpha x = go x k ++ unCaesar xs k
| otherwise = caesar xs k
where go c key = [enc c (-) key]
enc :: Char -> (Int -> Int -> Int) -> Int -> Char
enc c f k
| isAlpha c = chr i
| otherwise = c
where i = (mod ci r) + (ord base)
ci = f ((ord c) - (ord base)) k
r = 26
base = 'a'

@ -0,0 +1,42 @@
module EnumFromTo where
eftBool :: Bool -> Bool -> [Bool]
-- eftBool False True = [False, True]
-- eftBool False False = [False]
-- eftBool True False = []
-- eftBool True True = [True]
-- eftBool a b
-- | a > b = []
-- | a == b = [a]
-- | otherwise = [a] ++ (eftBool (succ a) b)
eftBool = helper
eftOrd :: Ordering -> Ordering -> [Ordering]
-- eftOrd a b
-- | a > b = []
-- | a == b = [a]
-- | otherwise = [a] ++ (eftOrd (succ a) b)
eftOrd = helper
eftInt :: Int -> Int -> [Int]
-- eftInt a b
-- | a > b = []
-- | a == b = [a]
-- | otherwise = [a] ++ (eftInt (succ a) b)
eftInt = helper
eftChar :: Char -> Char -> [Char]
-- eftChar a b
-- | a > b = []
-- | a == b = [a]
-- | otherwise = [a] ++ (eftChar (succ a) b)
eftChar = helper
helper :: Enum a => a -> a -> [a]
helper a b
| ai > bi = []
| ai == bi = [a]
| otherwise = [a] ++ (helper (succ a) b)
where ai = fromEnum a
bi = fromEnum b

@ -0,0 +1,18 @@
module Filtering where
myFilter :: Integral a => [a] -> [a]
myFilter = filter (\x -> rem x 3 == 0)
myFilterLength :: Integral a => [a] -> Int
myFilterLength = length . myFilter
myFilter' :: [Char] -> [[Char]]
myFilter' = filter
(\x -> case x of
"the" -> False
"a" -> False
"an" -> False
_ -> True
)
. words

@ -0,0 +1,21 @@
module PoemLines where
firstSen :: [Char]
firstSen = "Tyger Tyger, burning bright\n"
secondSen :: [Char]
secondSen = "In the forests of the night\n"
thirdSen :: [Char]
thirdSen = "What immortal hand or eye\n"
fourthSen :: [Char]
fourthSen = "Could frame thy fearful\
\ symmetry?"
sentences :: [Char]
sentences = firstSen ++ secondSen
++ thirdSen ++ fourthSen
myLines :: String -> [String]
myLines [] = []
myLines ('\n' : xs) = myLines xs
myLines xs = [takeWhile b xs] ++ (myLines (dropWhile b xs))
where b = (/=) '\n'

@ -0,0 +1,25 @@
module Split where
-- Technically words and lines do not do the same thing. E.g
-- unwords . words $ " one two three " == "one two three"
-- unlines . lines $ "\none\n\ntwo\three" == "\none\n\ntwo\three\n"
-- i.e. words removes all spaces, lines splits between each '\n'
-- put otherwise: there are no empty words, but there are empty lines,
-- though there is no last empty line
-- The last part is evident by: lines "a\n" == ["a"] and lines "a" = ["a"]
-- The function here sees no empty words nor does it see empty lines
mySplit :: [Char] -> Char -> [[Char]]
mySplit [] _ = []
mySplit s@(x:xs) c
| x == c = mySplit xs c
| otherwise = [part1] ++ (mySplit part2 c)
where part1 = takeWhile b s
part2 = dropWhile b s
b = (/=) c
myWords :: [Char] -> [[Char]]
myWords = flip mySplit $ ' '
myLines :: [Char] -> [[Char]]
myLines = flip mySplit $ '\n'

@ -0,0 +1,18 @@
module SquareCube where
mySqr :: (Enum a, Num a) => [a]
mySqr = [x^(2 :: Integer) | x <- [1..5]]
myCube :: (Enum a, Num a) => [a]
myCube = [y^(3 :: Integer) | y <- [1..5]]
myTuples :: (Enum a, Num a) => [(a,a)]
myTuples = [(x,y) | x <- mySqr, y <- myCube]
myTuples' :: (Ord a, Enum a, Num a) => [(a,a)]
myTuples' = [(x,y) | x <- mySqr, y <- myCube,
x < 50, y < 50]
myTuples'Length :: Int
myTuples'Length = length (myTuples' :: [(Int,Int)])

@ -0,0 +1,67 @@
module Standards where
-- 1
myOr :: [Bool] -> Bool
myOr [] = True
myOr (x:xs) = x || myOr xs
-- 2
myAny :: (a -> Bool) -> [a] -> Bool
myAny _ [] = True
myAny f (x:xs) = f x || myAny f xs
-- 3
myElem :: Eq a => a -> [a] -> Bool
myElem _ [] = False
myElem a (x:xs) = (a == x) || myElem a xs
myElem' :: Eq a => a -> [a] -> Bool
myElem' a = any (a==)
-- 4
myReverse :: [a] -> [a]
myReverse [] = []
myReverse (x:xs) = myReverse xs ++ [x]
-- 5
squish :: [[a]] -> [a]
squish [] = []
squish (x:xs) = x ++ squish xs
-- 6
squishMap :: (a -> [b]) -> [a] -> [b]
squishMap _ [] = []
squishMap f (x:xs) = f x ++ squishMap f xs
-- 7
squishAgain :: [[a]] -> [a]
squishAgain = squishMap id
-- squishAgain = squishMap ([]++)
-- 8
myMaximumBy :: (a -> a -> Ordering) -> [a] -> a
myMaximumBy _ [] = undefined
myMaximumBy _ (x:[]) = x
myMaximumBy f (x:xs) =
case f x y of
LT -> y
_ -> x
where y = myMaximumBy f xs
-- 9
myMinimumBy :: (a -> a -> Ordering) -> [a] -> a
myMinimumBy _ [] = undefined
myMinimumBy _ (x:[]) = x
myMinimumBy f (x:xs) =
case f x y of
LT -> x
_ -> y
where y = myMinimumBy f xs
-- 10
myMaximum :: (Ord a) => [a] -> a
myMaximum = myMaximumBy compare
myMinimum :: (Ord a) => [a] -> a
myMinimum = myMinimumBy compare

@ -0,0 +1,7 @@
module Words where
myWords :: String -> [String]
myWords [] = []
myWords (' ' : xs) = myWords xs
myWords xs = [takeWhile b xs] ++ (myWords (dropWhile b xs))
where b = (/=) ' '

@ -0,0 +1,14 @@
module Zipping where
zip :: [a] -> [b] -> [(a,b)]
zip [] _ = []
zip _ [] = []
zip (x:xs) (y:ys) = [(x,y)] ++ (Zipping.zip xs ys)
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith _ [] _ = []
zipWith _ _ [] = []
zipWith f (x:xs) (y:ys) = [f x y] ++ (Zipping.zipWith f xs ys)
zip' :: [a] -> [b] -> [(a,b)]
zip' = Zipping.zipWith (,)
Loading…
Cancel
Save