From 3624c712d72d246f21d4e710cec7c11e052e0326 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 9 Dec 2025 16:32:32 +0100 Subject: [PATCH] Add the haskell book --- Haskell-book/02/.gitignore | 8 +++ Haskell-book/02/bower.json | 17 ++++++ Haskell-book/02/src/Main.purs | 28 +++++++++ Haskell-book/02/test/Main.purs | 9 +++ Haskell-book/03/.gitignore | 8 +++ Haskell-book/03/bower.json | 18 ++++++ Haskell-book/03/src/Main.purs | 45 ++++++++++++++ Haskell-book/03/test/Main.purs | 9 +++ Haskell-book/04/.gitignore | 8 +++ Haskell-book/04/bower.json | 20 ++++++ Haskell-book/04/src/Ex.purs | 33 ++++++++++ Haskell-book/04/src/Main.purs | 9 +++ Haskell-book/04/test/Main.purs | 9 +++ Haskell-book/05/.gitignore | 8 +++ Haskell-book/05/bower.json | 21 +++++++ Haskell-book/05/src/Arith3Broken.purs | 14 +++++ Haskell-book/05/src/Ex.purs | 36 +++++++++++ Haskell-book/05/src/Main.purs | 9 +++ Haskell-book/05/src/Sing.purs | 14 +++++ Haskell-book/05/src/TypeKwonDo.purs | 47 +++++++++++++++ Haskell-book/05/test/Main.purs | 9 +++ Haskell-book/06/.gitignore | 8 +++ Haskell-book/06/bower.json | 16 +++++ Haskell-book/06/src/EqInstances.purs | 63 +++++++++++++++++++ Haskell-book/06/src/Ex.purs | 9 +++ Haskell-book/06/src/Main.purs | 30 +++++++++ Haskell-book/06/test/Main.purs | 9 +++ Haskell-book/07/.gitignore | 8 +++ Haskell-book/07/bower.json | 19 ++++++ Haskell-book/07/src/ArtfulDodgy.purs | 13 ++++ Haskell-book/07/src/CasePractice.purs | 24 ++++++++ Haskell-book/07/src/Ex.purs | 70 +++++++++++++++++++++ Haskell-book/07/src/GrabBag.purs | 14 +++++ Haskell-book/07/src/Main.purs | 9 +++ Haskell-book/07/src/VarietyPack.purs | 9 +++ Haskell-book/07/test/Main.purs | 9 +++ Haskell-book/08/.gitignore | 8 +++ Haskell-book/08/bower.json | 22 +++++++ Haskell-book/08/src/Exercises.purs | 72 ++++++++++++++++++++++ Haskell-book/08/src/Main.purs | 9 +++ Haskell-book/08/src/WordNumber.purs | 30 +++++++++ Haskell-book/08/test/Main.purs | 9 +++ Haskell-book/09/.gitignore | 8 +++ Haskell-book/09/bower.json | 21 +++++++ Haskell-book/09/src/Cipher.purs | 15 +++++ Haskell-book/09/src/EnumFromTo.purs | 15 +++++ Haskell-book/09/src/Exercises.hs | 73 ++++++++++++++++++++++ Haskell-book/09/src/Exercises.purs | 27 +++++++++ Haskell-book/09/src/Filtering.purs | 8 +++ Haskell-book/09/src/Main.purs | 9 +++ Haskell-book/09/src/PoemLines.purs | 42 +++++++++++++ Haskell-book/09/src/SquareCube.purs | 25 ++++++++ Haskell-book/09/src/Zipping.purs | 27 +++++++++ Haskell-book/09/test/Main.purs | 9 +++ Haskell-book/10/Db.hs | 52 ++++++++++++++++ Haskell-book/10/Exercise.hs | 53 ++++++++++++++++ Haskell-book/11/As.hs | 30 +++++++++ Haskell-book/11/BinaryTree.hs | 87 +++++++++++++++++++++++++++ Haskell-book/11/Cipher.hs | 24 ++++++++ Haskell-book/11/Garden.hs | 11 ++++ Haskell-book/11/Hutton.hs | 13 ++++ Haskell-book/11/Phone.hs | 87 +++++++++++++++++++++++++++ Haskell-book/11/Programmer.hs | 40 ++++++++++++ Haskell-book/11/TooMany.hs | 16 +++++ Haskell-book/11/Vehicle.hs | 40 ++++++++++++ Haskell-book/README.txt | 1 + README.md | 4 ++ 67 files changed, 1576 insertions(+) create mode 100644 Haskell-book/02/.gitignore create mode 100644 Haskell-book/02/bower.json create mode 100644 Haskell-book/02/src/Main.purs create mode 100644 Haskell-book/02/test/Main.purs create mode 100644 Haskell-book/03/.gitignore create mode 100644 Haskell-book/03/bower.json create mode 100644 Haskell-book/03/src/Main.purs create mode 100644 Haskell-book/03/test/Main.purs create mode 100644 Haskell-book/04/.gitignore create mode 100644 Haskell-book/04/bower.json create mode 100644 Haskell-book/04/src/Ex.purs create mode 100644 Haskell-book/04/src/Main.purs create mode 100644 Haskell-book/04/test/Main.purs create mode 100644 Haskell-book/05/.gitignore create mode 100644 Haskell-book/05/bower.json create mode 100644 Haskell-book/05/src/Arith3Broken.purs create mode 100644 Haskell-book/05/src/Ex.purs create mode 100644 Haskell-book/05/src/Main.purs create mode 100644 Haskell-book/05/src/Sing.purs create mode 100644 Haskell-book/05/src/TypeKwonDo.purs create mode 100644 Haskell-book/05/test/Main.purs create mode 100644 Haskell-book/06/.gitignore create mode 100644 Haskell-book/06/bower.json create mode 100644 Haskell-book/06/src/EqInstances.purs create mode 100644 Haskell-book/06/src/Ex.purs create mode 100644 Haskell-book/06/src/Main.purs create mode 100644 Haskell-book/06/test/Main.purs create mode 100644 Haskell-book/07/.gitignore create mode 100644 Haskell-book/07/bower.json create mode 100644 Haskell-book/07/src/ArtfulDodgy.purs create mode 100644 Haskell-book/07/src/CasePractice.purs create mode 100644 Haskell-book/07/src/Ex.purs create mode 100644 Haskell-book/07/src/GrabBag.purs create mode 100644 Haskell-book/07/src/Main.purs create mode 100644 Haskell-book/07/src/VarietyPack.purs create mode 100644 Haskell-book/07/test/Main.purs create mode 100644 Haskell-book/08/.gitignore create mode 100644 Haskell-book/08/bower.json create mode 100644 Haskell-book/08/src/Exercises.purs create mode 100644 Haskell-book/08/src/Main.purs create mode 100644 Haskell-book/08/src/WordNumber.purs create mode 100644 Haskell-book/08/test/Main.purs create mode 100644 Haskell-book/09/.gitignore create mode 100644 Haskell-book/09/bower.json create mode 100644 Haskell-book/09/src/Cipher.purs create mode 100644 Haskell-book/09/src/EnumFromTo.purs create mode 100644 Haskell-book/09/src/Exercises.hs create mode 100644 Haskell-book/09/src/Exercises.purs create mode 100644 Haskell-book/09/src/Filtering.purs create mode 100644 Haskell-book/09/src/Main.purs create mode 100644 Haskell-book/09/src/PoemLines.purs create mode 100644 Haskell-book/09/src/SquareCube.purs create mode 100644 Haskell-book/09/src/Zipping.purs create mode 100644 Haskell-book/09/test/Main.purs create mode 100644 Haskell-book/10/Db.hs create mode 100644 Haskell-book/10/Exercise.hs create mode 100644 Haskell-book/11/As.hs create mode 100644 Haskell-book/11/BinaryTree.hs create mode 100644 Haskell-book/11/Cipher.hs create mode 100644 Haskell-book/11/Garden.hs create mode 100644 Haskell-book/11/Hutton.hs create mode 100644 Haskell-book/11/Phone.hs create mode 100644 Haskell-book/11/Programmer.hs create mode 100644 Haskell-book/11/TooMany.hs create mode 100644 Haskell-book/11/Vehicle.hs create mode 100644 Haskell-book/README.txt diff --git a/Haskell-book/02/.gitignore b/Haskell-book/02/.gitignore new file mode 100644 index 0000000..9623fa5 --- /dev/null +++ b/Haskell-book/02/.gitignore @@ -0,0 +1,8 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.purs* +/.psa* diff --git a/Haskell-book/02/bower.json b/Haskell-book/02/bower.json new file mode 100644 index 0000000..8771a39 --- /dev/null +++ b/Haskell-book/02/bower.json @@ -0,0 +1,17 @@ +{ + "name": "02", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-prelude": "^3.1.0", + "purescript-console": "^3.0.0", + "purescript-math": "^2.1.0" + }, + "devDependencies": { + "purescript-psci-support": "^3.0.0" + } +} diff --git a/Haskell-book/02/src/Main.purs b/Haskell-book/02/src/Main.purs new file mode 100644 index 0000000..feb0fd2 --- /dev/null +++ b/Haskell-book/02/src/Main.purs @@ -0,0 +1,28 @@ +module Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) +import Math (pi) + +-- +-- 2.5 Comprehensive check +-- +mulSquare :: Number -> Number +mulSquare x = pi * (x * x) + +waxOn :: Int +waxOn = x * 5 + where x = y * y + y = z + 8 + z = 7 + +triple :: Int -> Int +triple x = x * 3 + +waxOff :: Int -> Int +waxOff = triple + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "Hello sailor!" diff --git a/Haskell-book/02/test/Main.purs b/Haskell-book/02/test/Main.purs new file mode 100644 index 0000000..845d0f4 --- /dev/null +++ b/Haskell-book/02/test/Main.purs @@ -0,0 +1,9 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "You should add some tests." diff --git a/Haskell-book/03/.gitignore b/Haskell-book/03/.gitignore new file mode 100644 index 0000000..9623fa5 --- /dev/null +++ b/Haskell-book/03/.gitignore @@ -0,0 +1,8 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.purs* +/.psa* diff --git a/Haskell-book/03/bower.json b/Haskell-book/03/bower.json new file mode 100644 index 0000000..9944a06 --- /dev/null +++ b/Haskell-book/03/bower.json @@ -0,0 +1,18 @@ +{ + "name": "03", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-prelude": "^3.1.0", + "purescript-console": "^3.0.0", + "purescript-arrays": "^4.2.1", + "purescript-strings": "^3.3.1" + }, + "devDependencies": { + "purescript-psci-support": "^3.0.0" + } +} diff --git a/Haskell-book/03/src/Main.purs b/Haskell-book/03/src/Main.purs new file mode 100644 index 0000000..d73dc74 --- /dev/null +++ b/Haskell-book/03/src/Main.purs @@ -0,0 +1,45 @@ +module Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) +import Data.String (singleton, drop, take) +import Data.String.Unsafe (charAt) + +-- Given +-- "Curry is awesome" +-- Return +-- "Curry is awesome!" +a :: String -> String +a x = x <> "!" + +-- Given +-- "Curry is awesome!" +-- Return +-- "y" +b :: String -> String +b x = singleton $ charAt 4 x + +-- Given +-- "Curry is awesome!" +-- Return +-- "awesome!" +c :: String -> String +c = drop 9 + +-- If you apply your function to this value: +-- "Curry is awesome" +-- Your function should return +-- 'r' +thirdLetter :: String -> Char +thirdLetter = charAt 2 + +letterIndex :: Int -> Char +letterIndex x = charAt x "Curry is awesome!" + +rvrs :: String -> String +rvrs inp = (drop 9 inp) <> (drop 5 $ take 9 inp) <> (take 5 inp) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log $ rvrs "Curry is awesome" diff --git a/Haskell-book/03/test/Main.purs b/Haskell-book/03/test/Main.purs new file mode 100644 index 0000000..845d0f4 --- /dev/null +++ b/Haskell-book/03/test/Main.purs @@ -0,0 +1,9 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "You should add some tests." diff --git a/Haskell-book/04/.gitignore b/Haskell-book/04/.gitignore new file mode 100644 index 0000000..9623fa5 --- /dev/null +++ b/Haskell-book/04/.gitignore @@ -0,0 +1,8 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.purs* +/.psa* diff --git a/Haskell-book/04/bower.json b/Haskell-book/04/bower.json new file mode 100644 index 0000000..e6c4ee1 --- /dev/null +++ b/Haskell-book/04/bower.json @@ -0,0 +1,20 @@ +{ + "name": "04", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-prelude": "^3.1.0", + "purescript-console": "^3.0.0", + "purescript-tuples": "^4.1.0", + "purescript-lists": "^4.10.0", + "purescript-arrays": "^4.2.1", + "purescript-strings": "^3.3.1" + }, + "devDependencies": { + "purescript-psci-support": "^3.0.0" + } +} diff --git a/Haskell-book/04/src/Ex.purs b/Haskell-book/04/src/Ex.purs new file mode 100644 index 0000000..38da5c4 --- /dev/null +++ b/Haskell-book/04/src/Ex.purs @@ -0,0 +1,33 @@ +module Ex where + +import Prelude +import Data.Array (tail, reverse) +import Data.Maybe (Maybe(..)) +import Data.String (toCharArray) +import Data.Tuple (fst, snd, Tuple(..)) + +awesome :: Array String +awesome = ["Papuchon", "curry", ":)"] + +alsoAwesome :: Array String +alsoAwesome = ["Quake", "The Simons"] + +allAwesome :: Array (Array String) +allAwesome = [awesome, alsoAwesome] + +length :: forall a. Array a -> Int +length n = length' 0 (tail n) + where length' i Nothing = i + length' i (Just k) = length' (i + 1) (tail k) + +isPalindrome :: String -> Boolean +isPalindrome x = toCharArray x == reverse (toCharArray x) + +myAbs :: Int -> Int +myAbs a = if a > 0 then a else -a + +f :: forall a b c d. Tuple a b -> Tuple c d -> Tuple (Tuple b d) (Tuple a c) +f x y = Tuple (Tuple (snd x) (snd y)) (Tuple (fst x) (fst y)) + +f' :: forall a b. (Tuple a b) -> a +f' (Tuple a b) = a diff --git a/Haskell-book/04/src/Main.purs b/Haskell-book/04/src/Main.purs new file mode 100644 index 0000000..abe68ec --- /dev/null +++ b/Haskell-book/04/src/Main.purs @@ -0,0 +1,9 @@ +module Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "Hello sailor!" diff --git a/Haskell-book/04/test/Main.purs b/Haskell-book/04/test/Main.purs new file mode 100644 index 0000000..845d0f4 --- /dev/null +++ b/Haskell-book/04/test/Main.purs @@ -0,0 +1,9 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "You should add some tests." diff --git a/Haskell-book/05/.gitignore b/Haskell-book/05/.gitignore new file mode 100644 index 0000000..9623fa5 --- /dev/null +++ b/Haskell-book/05/.gitignore @@ -0,0 +1,8 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.purs* +/.psa* diff --git a/Haskell-book/05/bower.json b/Haskell-book/05/bower.json new file mode 100644 index 0000000..e443dfd --- /dev/null +++ b/Haskell-book/05/bower.json @@ -0,0 +1,21 @@ +{ + "name": "05", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-prelude": "^3.1.0", + "purescript-console": "^3.0.0", + "purescript-tuples": "^4.1.0", + "purescript-strings": "^3.3.1", + "purescript-arrays": "^4.2.1", + "purescript-lists": "^4.10.0", + "purescript-unsafe-coerce": "^3.0.0" + }, + "devDependencies": { + "purescript-psci-support": "^3.0.0" + } +} diff --git a/Haskell-book/05/src/Arith3Broken.purs b/Haskell-book/05/src/Arith3Broken.purs new file mode 100644 index 0000000..e3938a4 --- /dev/null +++ b/Haskell-book/05/src/Arith3Broken.purs @@ -0,0 +1,14 @@ +-- arith3broken.hs +module Arith3Broken where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log $ show (1 + 5) + log "10" + log $ show (negate $ -1) + log $ show ((+) 0 blah) + where blah = negate 1 diff --git a/Haskell-book/05/src/Ex.purs b/Haskell-book/05/src/Ex.purs new file mode 100644 index 0000000..b075de4 --- /dev/null +++ b/Haskell-book/05/src/Ex.purs @@ -0,0 +1,36 @@ +module Ex where + +import Data.Array (head) +import Data.Maybe (Maybe) +import Data.Tuple (Tuple(..)) +import Prelude + +functionH :: forall a. Array a -> Maybe a +functionH x = head x + +functionC :: forall a. Ord a => a -> a -> Boolean +functionC x y = if (x > y) then true else false + +functionS :: forall a b. Tuple a b -> b +functionS (Tuple x y) = y + +i :: forall a. a -> a +i x = x + +c :: forall a b. a -> b -> a +c x _ = x + +c'' :: forall a b. b -> a -> b +c'' x _ = x + +c' :: forall a b. a -> b -> b +c' _ y = y + +r :: forall a. Array a -> Array a +r x = x + +co :: forall a b c. (b -> c) -> (a -> b) -> a -> c +co f f' x = f $ f' x + +a :: forall a c. (a -> c) -> a -> a +a _ x = x diff --git a/Haskell-book/05/src/Main.purs b/Haskell-book/05/src/Main.purs new file mode 100644 index 0000000..5674f56 --- /dev/null +++ b/Haskell-book/05/src/Main.purs @@ -0,0 +1,9 @@ +module Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE) +import Arith3Broken as Arith3Broken + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = Arith3Broken.main diff --git a/Haskell-book/05/src/Sing.purs b/Haskell-book/05/src/Sing.purs new file mode 100644 index 0000000..2ca173e --- /dev/null +++ b/Haskell-book/05/src/Sing.purs @@ -0,0 +1,14 @@ +module Sing where + +import Prelude + +fstString :: String -> String +fstString x = x <> " in the rain" + +sndString :: String -> String +sndString x = x <> " over the rainbow" + +sing :: String +sing = if (x > y) then fstString x else sndString y + where x = "Singin" + y = "Somewhere" diff --git a/Haskell-book/05/src/TypeKwonDo.purs b/Haskell-book/05/src/TypeKwonDo.purs new file mode 100644 index 0000000..9948502 --- /dev/null +++ b/Haskell-book/05/src/TypeKwonDo.purs @@ -0,0 +1,47 @@ +module TypeKwonDo where + +import Data.Tuple (Tuple(..), fst) +import Prelude +import Unsafe.Coerce (unsafeCoerce) + +f :: Int -> String +f = unsafeCoerce unit + +g :: String -> Char +g = unsafeCoerce unit + +h :: Int -> Char +h x = g $ f x + +data A +data B +data C + +q :: A -> B +q = unsafeCoerce unit + +w :: B -> C +w = unsafeCoerce unit + +e :: A -> C +e x = w $ q x + +data X +data Y +data Z + +xz :: X -> Z +xz = unsafeCoerce unit + +yz :: Y -> Z +yz = unsafeCoerce unit + +xform :: Tuple X Y -> Tuple Z Z +xform (Tuple a b) = Tuple (xz a) (yz b) + +munge :: forall x y z w. + (x -> y) + -> (y -> (Tuple w z)) + -> x + -> w +munge f1 f2 a = fst (f2 (f1 a)) diff --git a/Haskell-book/05/test/Main.purs b/Haskell-book/05/test/Main.purs new file mode 100644 index 0000000..845d0f4 --- /dev/null +++ b/Haskell-book/05/test/Main.purs @@ -0,0 +1,9 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "You should add some tests." diff --git a/Haskell-book/06/.gitignore b/Haskell-book/06/.gitignore new file mode 100644 index 0000000..9623fa5 --- /dev/null +++ b/Haskell-book/06/.gitignore @@ -0,0 +1,8 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.purs* +/.psa* diff --git a/Haskell-book/06/bower.json b/Haskell-book/06/bower.json new file mode 100644 index 0000000..f4358bf --- /dev/null +++ b/Haskell-book/06/bower.json @@ -0,0 +1,16 @@ +{ + "name": "06", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-prelude": "^3.1.0", + "purescript-console": "^3.0.0" + }, + "devDependencies": { + "purescript-psci-support": "^3.0.0" + } +} diff --git a/Haskell-book/06/src/EqInstances.purs b/Haskell-book/06/src/EqInstances.purs new file mode 100644 index 0000000..987d273 --- /dev/null +++ b/Haskell-book/06/src/EqInstances.purs @@ -0,0 +1,63 @@ +module EqInstances where + -- Exercise: Eq Instances + -- p. 178 + +import Prelude + +-- Ex. 1 +data TisAnInteger = + TisAn Int + +instance eqTisAn :: Eq TisAnInteger where + eq x y = x == y + +-- Ex. 2 +data TwoIntegers = + Two Int Int + +instance ewTwoIntegers :: Eq TwoIntegers where + eq (Two x y) (Two x' y') = x == x' && y == y' + +-- Ex. 3 +data StringOrInt = + TisAnInt Int + | TisAString String + +instance eqStringOrInt :: Eq StringOrInt where + eq (TisAnInt x) (TisAnInt y) = x == y + eq (TisAString x) (TisAString y) = x == y + eq _ _ = false + +-- Ex. 4 +data Pair a = + Pair a a + +instance eqPair :: Eq a => Eq (Pair a) where + eq (Pair a b) (Pair a' b') = a == a' && b == b' + +-- Ex. 5 +data Tuple a b = + Tuple a b + +instance eqTuple :: (Eq a, Eq b) => Eq (Tuple a b) where + eq (Tuple a b) (Tuple a' b') = a == a' && b == b' + +-- Ex. 6 +data Which a = + ThisOne a + | ThatOne a + +instance eqWhich :: Eq a => Eq (Which a) where + eq (ThisOne x) (ThisOne y) = x == y + eq (ThatOne x) (ThatOne y) = x == y + eq _ _ = false + +-- Ex. 7 +data EitherOr a b = + Hello a + | Goodbye b + +instance eqEitherOr :: (Eq a, Eq b) => Eq (EitherOr a b) where + eq (Hello _) (Goodbye _) = false + eq (Goodbye _) (Hello _) = false + eq _ _ = true diff --git a/Haskell-book/06/src/Ex.purs b/Haskell-book/06/src/Ex.purs new file mode 100644 index 0000000..290ad8e --- /dev/null +++ b/Haskell-book/06/src/Ex.purs @@ -0,0 +1,9 @@ +module Ex where + +import Prelude + +-- +-- Type-Kwon-Do Two: Electric Typealoo +-- +chk :: forall a b. Eq b => (a -> b) -> a -> b -> Boolean +chk f a b = (f a) == b diff --git a/Haskell-book/06/src/Main.purs b/Haskell-book/06/src/Main.purs new file mode 100644 index 0000000..6f60ab2 --- /dev/null +++ b/Haskell-book/06/src/Main.purs @@ -0,0 +1,30 @@ +module Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +data DayOfWeek = + Mon | Tue | Weds | Thu | Fri | Sat | Sun + +data Date = + Date DayOfWeek Int + +instance eqDayOfWeek :: Eq DayOfWeek where + eq Mon Mon = true + eq Tue Tue = true + eq Weds Weds = true + eq Thu Thu = true + eq Fri Fri = true + eq Sat Sat = true + eq Sun Sun = true + eq _ _ = false + +instance eqDate :: Eq Date where + eq (Date weekday dayOfMonth) + (Date weekday' dayOfMonth') = + weekday == weekday' && dayOfMonth == dayOfMonth' + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "Hello sailor!" diff --git a/Haskell-book/06/test/Main.purs b/Haskell-book/06/test/Main.purs new file mode 100644 index 0000000..845d0f4 --- /dev/null +++ b/Haskell-book/06/test/Main.purs @@ -0,0 +1,9 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "You should add some tests." diff --git a/Haskell-book/07/.gitignore b/Haskell-book/07/.gitignore new file mode 100644 index 0000000..9623fa5 --- /dev/null +++ b/Haskell-book/07/.gitignore @@ -0,0 +1,8 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.purs* +/.psa* diff --git a/Haskell-book/07/bower.json b/Haskell-book/07/bower.json new file mode 100644 index 0000000..3f3e066 --- /dev/null +++ b/Haskell-book/07/bower.json @@ -0,0 +1,19 @@ +{ + "name": "07", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-prelude": "^3.1.0", + "purescript-console": "^3.0.0", + "purescript-integers": "^3.1.0", + "purescript-tuples": "^4.1.0", + "purescript-unsafe-coerce": "^3.0.0" + }, + "devDependencies": { + "purescript-psci-support": "^3.0.0" + } +} diff --git a/Haskell-book/07/src/ArtfulDodgy.purs b/Haskell-book/07/src/ArtfulDodgy.purs new file mode 100644 index 0000000..5206c8d --- /dev/null +++ b/Haskell-book/07/src/ArtfulDodgy.purs @@ -0,0 +1,13 @@ +module ArtfulDodgy where + +import Prelude + +-- Exercise 1 +dodgy :: Int -> Int -> Int +dodgy x y = x + y * 10 + +oneIsOne :: Int -> Int +oneIsOne = dodgy 1 + +oneIsTwo :: Int -> Int +oneIsTwo = (flip dodgy) 2 diff --git a/Haskell-book/07/src/CasePractice.purs b/Haskell-book/07/src/CasePractice.purs new file mode 100644 index 0000000..8f8cbab --- /dev/null +++ b/Haskell-book/07/src/CasePractice.purs @@ -0,0 +1,24 @@ +module CasePractice where + +import Data.Int (even) +import Prelude + +-- Exercise 1 +functionC :: forall a. Ord a => a -> a -> a +functionC x y = case (x > y) of + true -> x + false -> y + +-- Exercise 2 +isEvenAdd2 :: Int -> Int +isEvenAdd2 n = case even n of + true -> n + 2 + false -> n + +-- Exercise 3 +nums :: Int -> Int +nums x = + case compare x 0 of + LT -> -1 + GT -> 1 + EQ -> 0 diff --git a/Haskell-book/07/src/Ex.purs b/Haskell-book/07/src/Ex.purs new file mode 100644 index 0000000..340917e --- /dev/null +++ b/Haskell-book/07/src/Ex.purs @@ -0,0 +1,70 @@ +module Ex where + +import Data.Int (fromString) +import Data.Maybe (Maybe(..)) +import Data.Tuple (Tuple(..)) +import Prelude +import Unsafe.Coerce (unsafeCoerce) + +-- +-- Multiple choice +-- +-- Exercise 2 +f :: Char -> String +f = unsafeCoerce unit + +g :: String -> Array String +g = unsafeCoerce unit + +e :: Char -> Array String +e = g <<< f + +-- Exercise 5 +f' :: forall a. a -> a +f' x = x + +g' :: Boolean +g' = f' true + +-- +-- Let's write code +-- + +-- Exercise 1 +tensDigit :: Int -> Int +tensDigit x = d + where xLast = x `div` 10 + d = xLast `mod` 10 + +-- Exercise 2 +hunsD :: Int -> Int +hunsD x = d + where xLast = x `div` 100 + d = xLast `mod` 10 + +foldBool :: forall a. a -> a -> Boolean -> a +foldBool x y z = case z of + false -> x + true -> y + +findBool2 :: forall a. a -> a -> Boolean -> a +findBool2 x y z + | z = y + | otherwise = x + +foldBool3 :: forall a. a -> a -> Boolean -> a +foldBool3 x _ false = x +foldBool3 _ y true = y + +-- Exercise 3 +g'' :: forall a b c. (a -> b) -> Tuple a c -> Tuple b c +g'' f'' (Tuple a c) = Tuple (f'' a) c + +-- Exercise 5 +-- id :: a -> a +-- id = x = x + +roundTrip :: Int -> Int +roundTrip = fromMaybe <<< fromString <<< show + where fromMaybe (Just n) = n + fromMaybe Nothing = unsafeCoerce unit diff --git a/Haskell-book/07/src/GrabBag.purs b/Haskell-book/07/src/GrabBag.purs new file mode 100644 index 0000000..2967002 --- /dev/null +++ b/Haskell-book/07/src/GrabBag.purs @@ -0,0 +1,14 @@ +module GrabBags where + +import Data.Int (odd) +import Prelude + +-- 3 a) +addOneIfOdd :: Int -> Int +addOneIfOdd n = case odd n of + true -> f n + false -> n + where f = \k -> k + 1 + +addFive :: (Int -> (Int -> Int)) +addFive = \x -> \y -> (if x > y then y else x) + 5 diff --git a/Haskell-book/07/src/Main.purs b/Haskell-book/07/src/Main.purs new file mode 100644 index 0000000..836cae9 --- /dev/null +++ b/Haskell-book/07/src/Main.purs @@ -0,0 +1,9 @@ +module Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log (id "4") diff --git a/Haskell-book/07/src/VarietyPack.purs b/Haskell-book/07/src/VarietyPack.purs new file mode 100644 index 0000000..602ae8d --- /dev/null +++ b/Haskell-book/07/src/VarietyPack.purs @@ -0,0 +1,9 @@ +module VarietyPack where + +import Data.Tuple (Tuple(..)) + +f :: forall a b c d e g + . Tuple (Tuple a b) c + -> Tuple (Tuple d e) g + -> Tuple (Tuple a d) (Tuple c g) +f (Tuple (Tuple a b) c) (Tuple (Tuple d e) g) = Tuple (Tuple a d) (Tuple c g) diff --git a/Haskell-book/07/test/Main.purs b/Haskell-book/07/test/Main.purs new file mode 100644 index 0000000..845d0f4 --- /dev/null +++ b/Haskell-book/07/test/Main.purs @@ -0,0 +1,9 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "You should add some tests." diff --git a/Haskell-book/08/.gitignore b/Haskell-book/08/.gitignore new file mode 100644 index 0000000..9623fa5 --- /dev/null +++ b/Haskell-book/08/.gitignore @@ -0,0 +1,8 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.purs* +/.psa* diff --git a/Haskell-book/08/bower.json b/Haskell-book/08/bower.json new file mode 100644 index 0000000..f6ad6e7 --- /dev/null +++ b/Haskell-book/08/bower.json @@ -0,0 +1,22 @@ +{ + "name": "08", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-prelude": "^3.1.0", + "purescript-console": "^3.0.0", + "purescript-tuples": "^4.1.0", + "purescript-generics-rep": "^5.3.0", + "purescript-arrays": "^4.2.1", + "purescript-foldable-traversable": "^3.6.1", + "purescript-unfoldable": "^3.0.0", + "purescript-maybe": "^3.0.0" + }, + "devDependencies": { + "purescript-psci-support": "^3.0.0" + } +} diff --git a/Haskell-book/08/src/Exercises.purs b/Haskell-book/08/src/Exercises.purs new file mode 100644 index 0000000..12460a8 --- /dev/null +++ b/Haskell-book/08/src/Exercises.purs @@ -0,0 +1,72 @@ +module Exercises where + +import Data.Tuple (Tuple(..), fst, snd) +import Prelude + +-- +-- Reviewing currying +-- +cattyConny :: String -> String -> String +cattyConny x y = x <> " mrow " <> y + +flippy :: String -> String -> String +flippy = flip cattyConny + +appedCatty :: String -> String +appedCatty = cattyConny "woops" + +frappe :: String -> String +frappe = flippy "haha" + +-- +-- Recursion +-- +-- Exercise 2 +sumNumbers :: Int -> Int +sumNumbers x = sumNumbers' x 0 + where sumNumbers' 0 acc = 0 + sumNumbers' n acc = n + (sumNumbers' (n - 1) acc) + +-- Exercise 2 +multiply :: Int -> Int -> Int +multiply _ 0 = 0 +multiply x 1 = x +multiply x y = x + multiply x (y - 1) + +-- +-- Fixing dividedBy +-- +data DividedResult = + Result Int + | DividedByZero + +instance showDividedResult :: Show DividedResult where + show :: DividedResult -> String + show (Result n) = show n + show DividedByZero = show "Divided by zero" + +go :: Int -> Int -> Int -> Tuple Int Int +go n d count + | n < d = Tuple count n + | otherwise = go (n - d) d (count + 1) + +abs :: Int -> Int +abs x + | x < 0 = -x + | otherwise = x + +dividedBy :: Int -> Int -> Tuple DividedResult DividedResult +dividedBy num denom + | denom == 0 = Tuple DividedByZero DividedByZero + | (num * denom) < 0 = let tuple = go (abs num) (abs denom) 0 in + Tuple (Result (-(fst tuple))) (Result (snd tuple)) + | otherwise = let tuple = go (abs num) (abs denom) 0 in + Tuple (Result (fst tuple)) (Result (snd tuple)) + +-- +-- McCarthy 91 function +-- +mc91 :: Int -> Int +mc91 n + | n > 100 = n - 10 + | otherwise = mc91 (mc91 (n + 11)) diff --git a/Haskell-book/08/src/Main.purs b/Haskell-book/08/src/Main.purs new file mode 100644 index 0000000..abe68ec --- /dev/null +++ b/Haskell-book/08/src/Main.purs @@ -0,0 +1,9 @@ +module Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "Hello sailor!" diff --git a/Haskell-book/08/src/WordNumber.purs b/Haskell-book/08/src/WordNumber.purs new file mode 100644 index 0000000..5d73db5 --- /dev/null +++ b/Haskell-book/08/src/WordNumber.purs @@ -0,0 +1,30 @@ +module WordNumber where + +import Data.Array (reverse) +import Data.Maybe (Maybe(..)) +import Data.String (joinWith) +import Data.Tuple (Tuple(..)) +import Data.Unfoldable (unfoldr) +import Prelude + +digitToWord :: Int -> String +digitToWord 0 = "null" +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 -> Array Int +digits n = reverse $ unfoldr unfold n + where unfold x + | x == 0 = Nothing + | otherwise = Just (Tuple (mod x 10) (div x 10)) + +wordNumber :: Int -> String +wordNumber n = joinWith "-" $ map digitToWord (digits n) diff --git a/Haskell-book/08/test/Main.purs b/Haskell-book/08/test/Main.purs new file mode 100644 index 0000000..845d0f4 --- /dev/null +++ b/Haskell-book/08/test/Main.purs @@ -0,0 +1,9 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "You should add some tests." diff --git a/Haskell-book/09/.gitignore b/Haskell-book/09/.gitignore new file mode 100644 index 0000000..9623fa5 --- /dev/null +++ b/Haskell-book/09/.gitignore @@ -0,0 +1,8 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.purs* +/.psa* diff --git a/Haskell-book/09/bower.json b/Haskell-book/09/bower.json new file mode 100644 index 0000000..f13cca6 --- /dev/null +++ b/Haskell-book/09/bower.json @@ -0,0 +1,21 @@ +{ + "name": "09", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-prelude": "^3.1.0", + "purescript-console": "^3.0.0", + "purescript-lists": "^4.10.0", + "purescript-arrays": "^4.2.1", + "purescript-maybe": "^3.0.0", + "purescript-enums": "^3.2.1", + "purescript-strings": "^3.3.1" + }, + "devDependencies": { + "purescript-psci-support": "^3.0.0" + } +} diff --git a/Haskell-book/09/src/Cipher.purs b/Haskell-book/09/src/Cipher.purs new file mode 100644 index 0000000..d5605c2 --- /dev/null +++ b/Haskell-book/09/src/Cipher.purs @@ -0,0 +1,15 @@ +module Cipher where + +import Data.Char (fromCharCode, toCharCode) +import Data.String (fromCharArray, toCharArray) +import Prelude + +caesar :: Int -> String -> String +caesar key s = fromCharArray $ map shiftRight (toCharArray s) + where shiftRight char = fromCharCode $ mod (ord char) 26 + ord = (add key) <<< toCharCode + +unCaesar :: Int -> String -> String +unCaesar key s = fromCharArray $ map shiftLeft (toCharArray s) + where shiftLeft char = fromCharCode $ ord char + ord chr = ((toCharCode chr) - (mod key 26)) + 26 diff --git a/Haskell-book/09/src/EnumFromTo.purs b/Haskell-book/09/src/EnumFromTo.purs new file mode 100644 index 0000000..f389c31 --- /dev/null +++ b/Haskell-book/09/src/EnumFromTo.purs @@ -0,0 +1,15 @@ +module EnumFromTo where + +import Data.Array ((:), reverse) +import Data.Enum (class Enum, succ) +import Data.Maybe (Maybe(..)) +import Prelude + +enumFromTo :: forall a. Enum a => a -> a -> Array a +enumFromTo start end = reverse $ enumFromTo' [] (Just start) + where enumFromTo' :: Array a -> Maybe a -> Array a + enumFromTo' acc (Just start') + | start' > end = acc + | start' == end = start' : acc + | otherwise = enumFromTo' (start' : acc) (succ start') + enumFromTo' acc Nothing = acc diff --git a/Haskell-book/09/src/Exercises.hs b/Haskell-book/09/src/Exercises.hs new file mode 100644 index 0000000..52ff797 --- /dev/null +++ b/Haskell-book/09/src/Exercises.hs @@ -0,0 +1,73 @@ +module Exercises where + +-- direct recursion, not using (&&) +myAnd :: [Bool] -> Bool +myAnd [] = True +myAnd (x:xs) = + if x == False + then False + else myAnd xs + +-- direct recursion, using (&&) +myAnd' :: [Bool] -> Bool +myAnd' [] = True +myAnd' (x:xs) = x && myAnd' xs + +-- 1 +myOr :: [Bool] -> Bool +myOr [] = False +myOr (x:xs) = x || myOr xs + +-- 2 +myAny :: (a -> Bool) -> [a] -> Bool +myAny f xs = myOr $ map f xs + +-- 3 +myElem :: Eq a => a -> [a] -> Bool +myElem _ [] = False +myElem y (x:xs) = (x == y) || (myElem y xs) + +-- 4 +myReverse :: [a] -> [a] +myReverse [] = [] +myReverse (x:xs) = (myReverse xs) ++ [x] + +-- 5 +squish :: [[a]] -> [a] +squish = squish' [] + where squish' acc [] = acc + squish' acc (x:xs) = x ++ (squish' acc xs) + +-- 6 +squishMap :: (a -> [b]) -> [a] -> [b] +squishMap _ [] = [] +squishMap f (x:xs) = (f x) ++ (squishMap f xs) + +-- 7 +squishAgain :: [[a]] -> [a] +squishAgain x = squishMap id x + +-- 8 +myMaximumBy :: (a -> a -> Ordering) + -> [a] -> a +myMaximumBy f (x:xs) = myMaximumBy' x xs + where myMaximumBy' m [] = m + myMaximumBy' m (y:ys) + | f y m == GT = myMaximumBy' y ys + | otherwise = myMaximumBy' m ys + +-- 9 +myMinimumBy :: (a -> a -> Ordering) + -> [a] -> a +myMinimumBy f (x:xs) = myMinimumBy' x xs + where myMinimumBy' m [] = m + myMinimumBy' m (y:ys) + | f y m == LT = myMinimumBy' y ys + | otherwise = myMinimumBy' m ys + +-- 10 +myMaximum :: (Ord a) => [a] -> a +myMaximum = myMaximumBy compare + +myMinimum :: (Ord a) => [a] -> a +myMinimum = myMinimumBy compare diff --git a/Haskell-book/09/src/Exercises.purs b/Haskell-book/09/src/Exercises.purs new file mode 100644 index 0000000..b18cf24 --- /dev/null +++ b/Haskell-book/09/src/Exercises.purs @@ -0,0 +1,27 @@ +module Exercises where + +import Data.Array (filter) +import Data.Char (toLower, toUpper) +import Data.Maybe (Maybe(..)) +import Data.String (fromCharArray, toCharArray, uncons) +import Prelude + +-- 2 +filterUppercase :: String -> String +filterUppercase s = fromCharArray $ filter (\x -> toLower x /= x) (toCharArray s) + +-- 3 +capitalize :: String -> String +capitalize s = maybeCapitalize $ uncons s + where maybeCapitalize Nothing = "" + maybeCapitalize (Just {head, tail}) = (fromCharArray $ [ toUpper head ]) <> tail + +-- 4 +capitalize' :: String -> String +capitalize' s = fromCharArray $ map toUpper $ toCharArray s + +-- 5 +firstLetter :: String -> Maybe Char +firstLetter = firstLetter' <<< uncons + where firstLetter' Nothing = Nothing + firstLetter' (Just {head, tail}) = Just $ toUpper head diff --git a/Haskell-book/09/src/Filtering.purs b/Haskell-book/09/src/Filtering.purs new file mode 100644 index 0000000..81257a8 --- /dev/null +++ b/Haskell-book/09/src/Filtering.purs @@ -0,0 +1,8 @@ +module Filtering where + +import Data.Array (filter) +import Data.String (split, Pattern(..)) +import Prelude + +myFilter :: String -> Array String +myFilter input = filter (\x -> x /= "a" && x /= "the") (split (Pattern " ") input) diff --git a/Haskell-book/09/src/Main.purs b/Haskell-book/09/src/Main.purs new file mode 100644 index 0000000..abe68ec --- /dev/null +++ b/Haskell-book/09/src/Main.purs @@ -0,0 +1,9 @@ +module Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "Hello sailor!" diff --git a/Haskell-book/09/src/PoemLines.purs b/Haskell-book/09/src/PoemLines.purs new file mode 100644 index 0000000..05a9a86 --- /dev/null +++ b/Haskell-book/09/src/PoemLines.purs @@ -0,0 +1,42 @@ +module PoemLines where + +import Data.Array ((:)) +import Data.String (takeWhile, dropWhile, drop) +import Prelude + +splitWith :: Char -> String -> Array String +splitWith _ "" = [] +splitWith sep s = (takeWhile cond s) : (splitWith sep $ drop 1 $ dropWhile cond s) + where cond x = x /= sep + +myWords :: String -> Array String +myWords = splitWith ' ' + +firstSen :: String +firstSen = "Tyger Tyger, burning bright\n" +secondSen :: String +secondSen = "In the forests of the night\n" +thirdSen :: String +thirdSen = "What immortal hand or eye\n" +fourthSen :: String +fourthSen = "Could frame thy fearful symmetry?" + +sentences :: String +sentences = firstSen <> secondSen <> thirdSen <> fourthSen +-- putStrLn sentences -- should print +-- Tyger Tyger, burning bright +-- In the forests of the night +-- What immortal hand or eye +-- Could frame thy fearful symmetry? + +myLines :: String -> Array String +myLines = splitWith '\n' + +got :: Array String +got = myLines sentences + +shouldEqual :: Array String +shouldEqual = [ "Tyger Tyger, burning bright" + , "In the forests of the night" + , "What immortal hand or eye" + , "Could frame thy fearful symmetry?" ] diff --git a/Haskell-book/09/src/SquareCube.purs b/Haskell-book/09/src/SquareCube.purs new file mode 100644 index 0000000..6316b4d --- /dev/null +++ b/Haskell-book/09/src/SquareCube.purs @@ -0,0 +1,25 @@ +module SquareCube where + +import Control.MonadZero (guard) +import Data.Array ((..)) +import Data.Int (pow) +import Data.Tuple (Tuple(..)) +import Prelude + +mySqr :: Array Int +mySqr = do + x <- 1 .. 5 + pure $ pow x 2 + +myCube :: Array Int +myCube = do + y <- 1 .. 5 + pure $ pow y 3 + +mySqrCube :: Array (Tuple Int Int) +mySqrCube = do + x <- mySqr + y <- myCube + guard $ x < 50 + guard $ y < 50 + pure $ Tuple x y diff --git a/Haskell-book/09/src/Zipping.purs b/Haskell-book/09/src/Zipping.purs new file mode 100644 index 0000000..32fe6da --- /dev/null +++ b/Haskell-book/09/src/Zipping.purs @@ -0,0 +1,27 @@ +module Zipping where + +import Data.Array (head, tail, (:)) +import Data.Maybe (Maybe(..)) +import Data.Tuple (Tuple(..)) + +-- 1 +zip :: forall a b. Array a -> Array b -> Array (Tuple a b) +zip a b = f (head a) (head b) (tail a) (tail b) + where f Nothing _ _ _ = [] + f _ Nothing _ _ = [] + f _ _ Nothing _ = [] + f _ _ _ Nothing = [] + f (Just x) (Just y) (Just xs) (Just ys) = (Tuple x y) : (f (head xs) (head ys) (tail xs) (tail ys)) + +-- 2 +zipWith :: forall a b c. (a -> b -> c) -> Array a -> Array b -> Array c +zipWith f a b = f' (head a) (head b) (tail a) (tail b) + where f' Nothing _ _ _ = [] + f' _ Nothing _ _ = [] + f' _ _ Nothing _ = [] + f' _ _ _ Nothing = [] + f' (Just x) (Just y) (Just xs) (Just ys) = (f x y) : (f' (head xs) (head ys) (tail xs) (tail ys)) + +-- 3 +zip' :: forall a b. Array a -> Array b -> Array (Tuple a b) +zip' = zipWith (\a b -> Tuple a b) diff --git a/Haskell-book/09/test/Main.purs b/Haskell-book/09/test/Main.purs new file mode 100644 index 0000000..845d0f4 --- /dev/null +++ b/Haskell-book/09/test/Main.purs @@ -0,0 +1,9 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, log) + +main :: forall e. Eff (console :: CONSOLE | e) Unit +main = do + log "You should add some tests." diff --git a/Haskell-book/10/Db.hs b/Haskell-book/10/Db.hs new file mode 100644 index 0000000..108f5ab --- /dev/null +++ b/Haskell-book/10/Db.hs @@ -0,0 +1,52 @@ +module Db where + +import Data.Time + +data DatabaseItem = DbString String + | DbNumber Integer + | DbDate UTCTime + deriving (Eq, Ord, Show) + +theDatabase :: [DatabaseItem] +theDatabase = + [ DbDate (UTCTime (fromGregorian 1911 5 1) (secondsToDiffTime 34123)) + , DbNumber 9001 + , DbString "Hello, world!" + , DbDate (UTCTime (fromGregorian 1921 5 1) (secondsToDiffTime 34123)) + ] + +filterDbDate :: [DatabaseItem] -> [UTCTime] +filterDbDate xs = foldr f1 [] (filter f2 xs) + where f1 (DbDate d) acc = d : acc + f2 (DbDate d) = True + f2 _ = False + +filterDbNumber :: [DatabaseItem] -> [Integer] +filterDbNumber xs = foldr f1 [] (filter f2 xs) + where f1 (DbNumber d) acc = d : acc + f2 (DbNumber d) = True + f2 _ = False + +mostRecent :: [DatabaseItem] -> UTCTime +mostRecent xs = maximum (filterDbDate xs) + +sumDb :: [DatabaseItem] -> Integer +sumDb xs = foldr (+) 0 (filterDbNumber xs) + +avgDb :: [DatabaseItem] -> Double +avgDb xs = (fromIntegral (sumDb xs)) / (fromIntegral (length (filterDbNumber xs))) + +fibs :: [Integer] +fibs = 1 : scanl (+) 1 fibs + +fibs20 :: [Integer] +fibs20 = take 20 (1 : scanl (+) 1 fibs) + +fibs100 :: [Integer] +fibs100 = takeWhile (\x -> x < 100) fibs + +fibsN :: Int -> Integer +fibsN x = fibs !! x + +factorial :: [Integer] +factorial = scanl (*) 1 [1..] diff --git a/Haskell-book/10/Exercise.hs b/Haskell-book/10/Exercise.hs new file mode 100644 index 0000000..8207e5e --- /dev/null +++ b/Haskell-book/10/Exercise.hs @@ -0,0 +1,53 @@ +module Exercise where + +stops :: String +stops = "pbtdkg" + +vowels :: String +vowels = "aeiou" + +stopVowelStop :: [(Char, Char, Char)] +stopVowelStop = filter p [(x, y, z) | x <- stops, y <- vowels, z <- stops] + where p (a, _, _) = a == 'p' + +seekritFunc :: String -> Double +seekritFunc x = (/) (fromIntegral (sum (map length (words x)))) (fromIntegral (length (words x))) + +myAnd :: [Bool] -> Bool +myAnd = foldr (&&) True + +myOr :: [Bool] -> Bool +myOr = foldr (||) False + +myAny :: (a -> Bool) -> [a] -> Bool +myAny f = myOr . map f + +myElem :: Eq a => a -> [a] -> Bool +myElem x = foldr (\y z -> z || (y == x)) False + +myElem' :: Eq a => a -> [a] -> Bool +myElem' needle = any (\x -> x == needle) + +myReverse :: [a] -> [a] +myReverse = foldl (flip (:)) [] + +myMap :: (a -> b) -> [a] -> [b] +myMap f = foldr (\x y -> (f x) : y) [] + +myFilter :: (a -> Bool) -> [a] -> [a] +myFilter f = foldr (\x xs -> if f x then x : xs else xs) [] + +squish :: [[a]] -> [a] +squish = foldr (++) [] + +squishMap :: (a -> [b]) -> [a] -> [b] +squishMap f xs = foldr (++) [] (map f xs) + +squishAgain :: [[a]] -> [a] +squishAgain = squishMap id + +myMaximumBy :: (a -> a -> Ordering) -> [a] -> a +myMaximumBy f (z:zs) = foldl (\x y -> if (f x y) == GT then x else y) z zs + +myMinimumBy :: (a -> a -> Ordering) -> [a] -> a +myMinimumBy f (z:zs) = foldl (\x y -> if (f x y) == LT then x else y) z zs diff --git a/Haskell-book/11/As.hs b/Haskell-book/11/As.hs new file mode 100644 index 0000000..744a5fe --- /dev/null +++ b/Haskell-book/11/As.hs @@ -0,0 +1,30 @@ +module As where + +import Data.Char + +isSubseqOf :: (Eq a) => [a] -> [a] -> Bool +isSubseqOf [] _ = True +isSubseqOf _ [] = False +isSubseqOf a@(x:xs) (y:ys) + | x == y = isSubseqOf xs ys + | otherwise = isSubseqOf a ys + +capitalize :: Char -> Char +capitalize x + | (ord x) >= (ord 'a') = (chr ((ord x) - 32)) + | otherwise = x + +capitalizeWords :: String -> [(String, String)] +capitalizeWords text = map f (words text) + where f w@(x:xs) = (w, (capitalize x) : xs) + +capitalizeWord :: String -> String +capitalizeWord (x:xs) = (capitalize x) : xs + +capitalizeParagraph :: String -> String +capitalizeParagraph = it True + where it _ [] = [] + it _ ('.':xs) = '.' : (it True xs) + it y (x:xs) + | (ord x) >= (ord 'a') && (ord x) < (ord 'z') && y = (capitalize x) : (it False xs) + | otherwise = x : (it y xs) diff --git a/Haskell-book/11/BinaryTree.hs b/Haskell-book/11/BinaryTree.hs new file mode 100644 index 0000000..854deee --- /dev/null +++ b/Haskell-book/11/BinaryTree.hs @@ -0,0 +1,87 @@ +module BinaryTree where + +data BinaryTree a = Leaf + | Node (BinaryTree a) a (BinaryTree a) + deriving (Eq, Ord, Show) + +insert' :: Ord a => a -> BinaryTree a -> BinaryTree a +insert' b Leaf = Node Leaf b Leaf +insert' b (Node left a right) + | b == a = Node left a right + | b < a = Node (insert' b left) a right + | b > a = Node left a (insert' b right) + +mapTree :: (a -> b) -> BinaryTree a -> BinaryTree b +mapTree _ Leaf = Leaf +mapTree f (Node left v right) = + Node (mapTree f left) (f v) (mapTree f right) + +preorder :: BinaryTree a -> [a] +preorder Leaf = [] +preorder (Node left v right) = + v : ((preorder left) ++ (preorder right)) + +inorder :: BinaryTree a -> [a] +inorder Leaf = [] +inorder (Node left v right) = + (inorder left) ++ [v] ++ (inorder right) + +postorder :: BinaryTree a -> [a] +postorder Leaf = [] +postorder (Node left v right) = + ((postorder left) ++ (postorder right)) ++ [v] + +foldTree :: (a -> b -> b) + -> b + -> BinaryTree a + -> b +foldTree _ acc Leaf = acc +foldTree f acc (Node left v right) = foldTree f r left + where r = foldTree f (f v acc) right + +testTree :: BinaryTree Integer +testTree = + Node (Node Leaf 1 Leaf) + 2 + (Node Leaf 3 Leaf) + +testPreorder :: IO () +testPreorder = + if preorder testTree == [2, 1, 3] + then putStrLn "Preorder fine!" + else putStrLn "Bad news bears." + +testInorder :: IO () +testInorder = + if inorder testTree == [1, 2, 3] + then putStrLn "Inorder fine!" + else putStrLn "Bad news bears." + +testPostorder :: IO () +testPostorder = + if postorder testTree == [1, 3, 2] + then putStrLn "Postorder fine!" + else putStrLn "postorder failed check" + +main :: IO () +main = do + testPreorder + testInorder + testPostorder + +testTree' :: BinaryTree Integer +testTree' = + Node (Node Leaf 3 Leaf) + 1 + (Node Leaf 4 Leaf) + +mapExpected = + Node (Node Leaf 4 Leaf) + 2 + (Node Leaf 5 Leaf) + +-- acceptance test for mapTree +mapOkay = + if mapTree (+1) testTree' == mapExpected + then print "yup okay!" + else error "test failed!" diff --git a/Haskell-book/11/Cipher.hs b/Haskell-book/11/Cipher.hs new file mode 100644 index 0000000..92e0e7d --- /dev/null +++ b/Haskell-book/11/Cipher.hs @@ -0,0 +1,24 @@ +module Cipher where + +import Data.Char +import Data.List + +decode :: (Char, Int) -> Char +decode (x, y) = chr ((mod ((ord x) - 65 + y) 26) + 65) + +decodeWithKey :: [Int] -> String -> String +decodeWithKey _ [] = [] +decodeWithKey ys (' ':xs) = ' ' : (decodeWithKey ys xs) +decodeWithKey (y:ys) (x:xs) = (decode (x, y)) : (decodeWithKey ys xs) + +vigenere :: String -> String +vigenere = decodeWithKey (cycle [0, 11, 11, 24]) + +caeser :: String -> String +caeser = decodeWithKey (cycle [11]) + +main :: IO () +main = do + putStrLn (vigenere "MEET AT DAWN") + putStrLn (caeser "MEET AT DAWN") + return () diff --git a/Haskell-book/11/Garden.hs b/Haskell-book/11/Garden.hs new file mode 100644 index 0000000..4211445 --- /dev/null +++ b/Haskell-book/11/Garden.hs @@ -0,0 +1,11 @@ +module Garden where + +data FlowerType = Gardenia + | Daisy + | Rose + | Lilac + deriving Show + +type Gardener = String + +data Garden = Garden Gardener FlowerType deriving Show diff --git a/Haskell-book/11/Hutton.hs b/Haskell-book/11/Hutton.hs new file mode 100644 index 0000000..539ba65 --- /dev/null +++ b/Haskell-book/11/Hutton.hs @@ -0,0 +1,13 @@ +module Hutton where + +data Expr + = Lit Integer + | Add Expr Expr + +eval :: Expr -> Integer +eval (Lit x) = x +eval (Add x y) = (eval x) + (eval y) + +printExpr :: Expr -> String +printExpr (Lit x) = show x +printExpr (Add x y) = (printExpr x) ++ " + " ++ (printExpr y) diff --git a/Haskell-book/11/Phone.hs b/Haskell-book/11/Phone.hs new file mode 100644 index 0000000..99976eb --- /dev/null +++ b/Haskell-book/11/Phone.hs @@ -0,0 +1,87 @@ +module Phone where + +import Data.Char (ord) +import Data.List (sortBy) + +data DaPhone = DaPhone + +convo :: [String] +convo = + [ "Wanna play 20 questions" + , "Ya" + , "U 1st haha" + , "Lol ok. Have u ever tasted alcohol" + , "Lol ya" + , "Wow ur cool haha. Ur turn" + , "Ok. Do u think I am pretty Lol" + , "Lol ya" + , "Just making sure rofl ur turn" ] + +-- validButtons = "1234567890*#" +type Digit = Char + +-- Valid presses: 1 and up +type Presses = Int + +data Button = Button Digit String + +-- assuming the default phone definition +-- 'a' -> [('2', 1)] +-- 'A' -> [('*', 1), ('2', 1)] +reverseTaps :: DaPhone -> Char -> [(Digit, Presses)] +reverseTaps _ c + | c == '.' = [('#', 1)] + | c == ',' = [('#', 2)] + | c == '#' = [('#', 3)] + | c == '+' = [('0', 1)] + | c == ' ' = [('0', 2)] + | c == '0' = [('0', 3)] + | (ord c) >= (ord 'w') = [('9', (ord c) - (ord 'w') + 1)] + | (ord c) >= (ord 't') = [('8', (ord c) - (ord 't') + 1)] + | (ord c) >= (ord 'p') = [('7', (ord c) - (ord 'p') + 1)] + | (ord c) >= (ord 'm') = [('6', (ord c) - (ord 'm') + 1)] + | (ord c) >= (ord 'j') = [('5', (ord c) - (ord 'j') + 1)] + | (ord c) >= (ord 'g') = [('4', (ord c) - (ord 'g') + 1)] + | (ord c) >= (ord 'd') = [('3', (ord c) - (ord 'd') + 1)] + | (ord c) >= (ord 'a') = [('2', (ord c) - (ord 'a') + 1)] + | (ord c) >= (ord 'W') = [('*', 1), ('9', (ord c) - (ord 'W') + 1)] + | (ord c) >= (ord 'T') = [('*', 1), ('8', (ord c) - (ord 'T') + 1)] + | (ord c) >= (ord 'P') = [('*', 1), ('7', (ord c) - (ord 'P') + 1)] + | (ord c) >= (ord 'M') = [('*', 1), ('6', (ord c) - (ord 'M') + 1)] + | (ord c) >= (ord 'J') = [('*', 1), ('5', (ord c) - (ord 'J') + 1)] + | (ord c) >= (ord 'G') = [('*', 1), ('4', (ord c) - (ord 'G') + 1)] + | (ord c) >= (ord 'D') = [('*', 1), ('3', (ord c) - (ord 'D') + 1)] + | (ord c) >= (ord 'A') = [('*', 1), ('2', (ord c) - (ord 'A') + 1)] + | c == '9' = [('9', 5)] + | c == '8' = [('8', 4)] + | c == '7' = [('7', 5)] + | c == '6' = [('6', 4)] + | c == '5' = [('5', 4)] + | c == '4' = [('4', 4)] + | c == '3' = [('3', 4)] + | c == '2' = [('2', 4)] + | c == '1' = [('2', 1)] + +cellPhonesDead :: DaPhone -> String -> [(Digit, Presses)] +cellPhonesDead dp s = concat (map (reverseTaps dp) s) + +fingerTaps :: [(Digit, Presses)] -> Presses +fingerTaps = foldr f 0 + where f (_, p) acc = p + acc + +mostPopularLetter :: String -> Char +mostPopularLetter c = fst $ head (sortBy (\(_, x1) (_, x2) -> compare x2 x1) $ foldr foldF [] c) + where foldF c [] = [(c, 1)] + foldF c ((x, n):xs) + | c == x = (x, n + 1) : xs + | otherwise = (x, n) : (foldF c xs) + +coolestLtr :: [String] -> Char +coolestLtr = mostPopularLetter . concat + +coolestWord :: [String] -> String +coolestWord c = fst $ head (sortBy (\(_, x1) (_, x2) -> compare x2 x1) $ foldr foldF [] (words (concat c))) + where foldF c [] = [(c, 1)] + foldF c ((x, n):xs) + | c == x = (x, n + 1) : xs + | otherwise = (x, n) : (foldF c xs) diff --git a/Haskell-book/11/Programmer.hs b/Haskell-book/11/Programmer.hs new file mode 100644 index 0000000..4d27fe0 --- /dev/null +++ b/Haskell-book/11/Programmer.hs @@ -0,0 +1,40 @@ +module Programmer where + +data OperatingSystem = GnuPlusLinux + | OpenBSDPlusNevermindJustBSDStill + | Mac + | Windows + deriving (Eq, Show) + +data ProgLang = Haskell + | Agda + | Idris + | PureScript + deriving (Eq, Show) + +data Programmer = Programmer { os :: OperatingSystem + , lang :: ProgLang } + deriving (Eq, Show) + +allOperatingSystems :: [OperatingSystem] +allOperatingSystems = + [ GnuPlusLinux + , OpenBSDPlusNevermindJustBSDStill + , Mac + , Windows + ] + +allLanguages :: [ProgLang] +allLanguages = + [ Haskell + , Agda + , Idris + , PureScript + ] + +allProgrammers :: [Programmer] +allProgrammers = do + o <- allOperatingSystems + l <- allLanguages + return Programmer { os = o + , lang = l } diff --git a/Haskell-book/11/TooMany.hs b/Haskell-book/11/TooMany.hs new file mode 100644 index 0000000..633c6b2 --- /dev/null +++ b/Haskell-book/11/TooMany.hs @@ -0,0 +1,16 @@ +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE FlexibleInstances #-} +module TooMany where + +newtype Goats = Goats Int deriving (Eq, Show, TooMany) + +newtype Cows = Cows Int deriving (Eq, Show) + +class TooMany a where + tooMany :: a -> Bool + +instance TooMany Int where + tooMany n = n > 42 + +instance TooMany (Int, String) where + tooMany (n, _) = n > 42 diff --git a/Haskell-book/11/Vehicle.hs b/Haskell-book/11/Vehicle.hs new file mode 100644 index 0000000..b4dd705 --- /dev/null +++ b/Haskell-book/11/Vehicle.hs @@ -0,0 +1,40 @@ +module Vehicle where + +data Price = Price Integer deriving (Eq, Show) + +data Size = Size Integer deriving (Eq, Show) + +data Manufacturer = Mini + | Mazda + | Tata + deriving (Eq, Show) + +data Airline = PapuAir + | CatapultsR'Us + | TakeYourChancesUnited + deriving (Eq, Show) + +data Vehicle = Car Manufacturer Price + | Plane Airline Size + deriving (Eq, Show) + +myCar = Car Mini (Price 14000) +urCar = Car Mazda (Price 20000) +clownCar = Car Tata (Price 7000) +doge = Plane PapuAir (Size 1234) + +isCar :: Vehicle -> Bool +isCar (Car _ _) = True +isCar _ = False + +isPlane :: Vehicle -> Bool +isPlane (Plane _ _) = True +isPlane _ = False + +areCars :: [Vehicle] -> [Bool] +areCars = map isCar + +getManu :: Vehicle -> Manufacturer +getManu (Car m _) = m + +data Example = MakeExample Int deriving Show diff --git a/Haskell-book/README.txt b/Haskell-book/README.txt new file mode 100644 index 0000000..178f948 --- /dev/null +++ b/Haskell-book/README.txt @@ -0,0 +1 @@ +Half of the exercises is done in PureScript and not in Haskell. diff --git a/README.md b/README.md index 90c4aa1..2af94b1 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,7 @@ This repository contains some excercises and projects from ## Java-Kompendium. Professionell Java programmieren lernen Von Markus Neumann. + +## Haskell Programming from first principles + +By Christopher Allen and Julie Moronuki.