# Lecture 4

## Maybe, yes? Maybe, no?

maybePlus :: Maybe Int -> Maybe Int -> Maybe Int
maybePlus ma mb = case ma of
Nothing -> Nothing
Just a  -> case mb of
Nothing -> Nothing
Just b  -> Just (a + b)

π₯Ίππ Awkward pattern matching

andThen :: Maybe Int -> (Int -> Maybe Int) -> Maybe Int
andThen ma f = case ma of
Nothing -> Nothing
Just x  -> f x
maybePlus :: Maybe Int -> Maybe Int -> Maybe Int
maybePlus ma mb = andThen ma (\a -> andThen mb (\b -> Just (a + b)))

π Ordinary helper function

π  Refactoring

andThen :: Maybe a -> (a -> Maybe b) -> Maybe b
andThen ma f = case ma of
Nothing -> Nothing
Just x  -> f x

## Either way

eitherPlus :: Either String Int -> Either String Int -> Either String Int
eitherPlus ea eb = case ea of
Left err -> Left err
Right a  -> case eb of
Left err -> Left err
Right b  -> Right (a + b)

π₯Ίππ Awkward pattern matching strikes again

andThen :: Either String Int
-> (Int -> Either String Int)
-> Either String Int
andThen ea f = case ea of
Left err -> Left err
Right x  -> f x
eitherPlus :: Either String Int -> Either String Int -> Either String Int
eitherPlus ea eb = andThen ea (\a -> andThen eb (\b -> Right (a + b)))

π Ordinary helper function

π  Refactoring

andThen :: Either e a
-> (a -> Either e b)
-> Either e b
andThen ea f = case ea of
Left err -> Left err
Right x  -> f x

## Multiple combinations

listPlus :: [Int] -> [Int] -> [Int]
listPlus la lb = case la of
[]     -> []
a : as -> case lb of
[] -> []
bs -> map (+ a) bs ++ listPlus as bs

π₯Ίππ Even more awkward pattern matching

andThen :: [Int] -> (Int -> [Int]) -> [Int]
andThen l f = case l of
[]     -> []
x : xs -> f x ++ andThen xs f
listPlus :: [Int] -> [Int] -> [Int]
listPlus la lb = andThen la (\a -> andThen lb (\b -> [a + b]))

π Ordinary helper function

π  Refactoring

andThen :: [a] -> (a -> [b]) -> [b]
andThen l f = case l of
[]     -> []
x : xs -> f x ++ andThen xs f

π The function became slower after refactoring!

## Is there a pattern?

andThen :: Maybe    a  -> (a -> Maybe    b)  -> Maybe    b
andThen :: Either e a  -> (a -> Either e b)  -> Either e b
andThen ::         [a] -> (a ->         [b]) ->         [b]

π Very similar type signatures

maybePlus  ma mb = andThen ma (\a -> andThen mb (\b -> Just  (a + b)))
eitherPlus ea eb = andThen ea (\a -> andThen eb (\b -> Right (a + b)))
listPlus   la lb = andThen la (\a -> andThen lb (\b ->       [a + b]))

π Almost the same implementations

## What to do when we see a pattern?

### 3. Copy-paste

π Monad is a generalization of the "andThen" pattern

### How to generalize? π€

We need:

1. Polymorphic andThen
2. Polymorphic constructor
maybePlus  ma mb = andThen ma (\a -> andThen mb (\b -> Just  (a + b)))
eitherPlus ea eb = andThen ea (\a -> andThen eb (\b -> Right (a + b)))
listPlus   la lb = andThen la (\a -> andThen lb (\b ->       [a + b]))

class Monad m where
return :: a -> m a
(>>=)  :: m a -> (a -> m b) -> m b

π§βπ What we can already learn from the definition

π« What we can't see from the above

2. It has two methods
3. The second method is an operator (it's called bind)
4. It's a typeclass for type constructors like Maybe and not e.g. Int
1. Instances implemementations
2. Laws
3. How to use this abstraction efficiently

## Instances

instance Monad Maybe where
return :: a -> Maybe a
return x = Just x

(>>=) :: Maybe a
-> (a -> Maybe b)
-> Maybe b
Nothing >>= _ = Nothing
Just x  >>= f = f x

βΉοΈ Maybe

class Monad m where
return :: a -> m a
(>>=)  :: m a -> (a -> m b) -> m b
instance Monad (Either e) where
return :: a -> Either e a
return x = Right x

(>>=) :: Either e a
-> (a -> Either e b)
-> Either e b
Left e  >>= _ = Left e
Right x >>= f = f x
instance Monad [] where
return :: a -> [a]
return x = [x]

(>>=) :: [a] -> (a -> [b]) -> [b]
l >>= f = concatMap f l

βΉοΈ Either

βΉοΈ List

## Laws

instance Monad Maybe where
return :: a -> Maybe a
return x = Just x

...

π Correct Monad instance for Maybe

Left identity

Right identity

Associativity

\mathrm{return} \ a\ \gg =\ f \equiv f \ a
m \ \gg = \ \mathrm{return} \equiv m
(m \gg = f) \gg = g \equiv m \gg = (\lambda x \rightarrow f \ x \gg = g)
instance Monad Maybe where
return :: a -> Maybe a
return x = Nothing

...

π Incorrect Monad instance for Maybe

## Generalizing

andThen ::            Maybe    a  -> (a -> Maybe    b)  -> Maybe    b
andThen ::            Either e a  -> (a -> Either e b)  -> Either e b
andThen ::                    [a] -> (a ->         [b]) ->         [b]

π Similar chaining functions

(>>=)   :: Monad m => m        a  -> (a -> m        b)  -> m        b

π Similar constructors

Just   ::            a -> Maybe    a
Right  ::            a -> Either e a
(:[])  ::            a ->         [a]    -- robot monkey operator
return :: Monad m => a -> m        a

## Refactoring

maybePlus :: Maybe Int -> Maybe Int -> Maybe Int
maybePlus ma mb = andThen ma (\a -> andThen mb (\b -> Just (a + b)))

0οΈβ£ Starting with the basics

maybePlus :: Maybe Int -> Maybe Int -> Maybe Int
maybePlus ma mb = ma andThen (\a -> mb andThen (\b -> Just (a + b)))
maybePlus :: Maybe Int -> Maybe Int -> Maybe Int
maybePlus ma mb = ma andThen \a -> mb andThen \b -> Just (a + b)

1οΈβ£ Using infix form of andThen

2οΈβ£ Removing redundant ()

maybePlus :: Maybe Int -> Maybe Int -> Maybe Int
maybePlus ma mb = ma >>= \a -> mb >>= \b -> return (a + b)
monadPlus :: Monad m => m Int -> m Int -> m Int
monadPlus ma mb = ma >>= \a -> mb >>= \b -> return (a + b)

3οΈβ£ Replacing andThen with >>=Β and Just with return

4οΈβ£Generalizing the type and changing the name

class Functor f where
fmap :: (a -> b) -> f a -> f b

class Functor f => Applicative f where
pure  :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b

class Applicative m => Monad m where
return :: a -> m a
return = pure

(>>=) :: m a -> (a -> m b) -> m b

βΉοΈ Monad is a part of FAMily

# Real World

## Purity π§

map :: (a -> b) -> [a] -> [b]

π Pure functions β functions without side-effects that depend only on their explicit input arguments.

## π§ Purity + Laziness π¦₯

getLine :: String

π€ How would a function that reads a line would look like?

ghci> getTwoLines !! 1
???????

getTwoLines :: [String]
getTwoLInes = [getLine, getLine]

π€π€π€ How this should work???

### Conclusion

π‘ We can't have side effects in Haskell without changing at least something. Otherwise, we'll lose the remainings of our sanity while working with the language.

## Input/Output (IO)

data IO a = ...

βΉοΈ Opaque data type IO

βΉοΈ Functions with side-effects

getLine :: IO String

π©βπ¬ getLine is a function that returns a value of type String and also performs some side-effects

βΉοΈ IO has the Monad instance

instance Monad IO where
return :: a -> IO a
(>>=)  :: IO a -> (a -> IO b) -> IO b
...

getTwoLines :: IO [String]
getTwoLines =
getLine >>= \line1 -> getLine >>= \line2 -> pure [line1, line2]

## Concept of IO

String
IO String

## How to run IO?

βΉοΈ A helper function to print to the terminal

putStrLn :: String -> IO ()

π©βπ¬ putStrLn is a function that takes a value of type String, prints it the terminal and doesn't return any meaningful value.

ghci> ()  -- a unit type
()
ghci> :t ()
() :: ()
ghci> putStrLn "Hi! π"
Hi! π
ghci> :t getLine
getLine :: IO String
ghci> getLine
Alice
"Alice"
ghci> fmap length getLine
Bob
3

## How to run Haskell programs?

module Main where

main :: IO ()
main = ... your program goes here ...

π©βπ¬ Haskell program starts with the main function in the module Main

module Main where

main :: IO ()
main = putStrLn "Hello, world!"

## Printing twice

βWe want to print two different lines

putStrLn :: String -> IO ()

π©βπ¬ We use the bind operator (>>=) and ignore the putStrLn resutl

module Main where

main :: IO ()
main = putStrLn "Hello, Alice!" >>= \_ -> putStrLn "Hello, Bob!"
(>>) :: Monad m => m a -> m b -> m b
action1 >> action2 = action1 >>= \_ -> action2

βΉοΈ A helper function

main :: IO ()
main = putStrLn "Hello, Alice!" >> putStrLn "Hello, Bob!"

βΉοΈ Slightly shorter version

## do

π do-notation β syntax sugar for >>=,Β >> and let-in

example1 =
fun1 >>= \result -> fun2 result
example1 = do
result <- fun1
fun2 result

βΉοΈ >>= rule

example1 = fun1 >>= fun2

Eta-reduced example1 with >>=

βΉοΈ >>Β rule

example2 = fun1 >> fun2
example2 = do
fun1
fun2

βΉοΈ let-in rule

example3 = let x = f y in fun x
example3 = do
let x = f y
fun x

## Example with do

βοΈ Write a program that reads a line and prints its reverse

main :: IO ()
main =
getLine >>= \line ->
let rev = reverse line in
putStrLn rev
main :: IO ()
main = do
line <- getLine
let rev = reverse line
putStrLn rev

### βοΈ Common mistake #1

let line = getLine
rev <- reverse line

π do-Style

# Cabal

## Cabal

π Cabal β format for describing structure of Haskell packages.

my-project/
βββ app/
β   βββ Main.hs
βββ src/
β   βββ MyModule.hs
β   βββ AnotherModule.hs
βββ my-project.cabal
cabal-version:      2.4
name:               my-project
version:            1.0.0.0

library
hs-source-dirs:      src
exposed-modules:     MyModule
AnotherModule

build-depends:       base ^>= 4.14

executable my-project
hs-source-dirs:   app
main-is:          Main.hs

build-depends:    my-project
, base

π Files with the .cabalΒ file extension describe the package.Β

π cabal-install β a Haskell build tool that works with Cabal packages.

## Typical main

module Main (main) where

import qualified MyModule

main :: IO ()
main = MyModule.main

## build-depends

library
hs-source-dirs:      src
exposed-modules:     MyModule

build-depends:       base       ^>= 4.14
, containers ^>= 0.6
, text       ^>= 1.2
, time       ^>= 1.9

π The build-depends field in the .cabal file specifies external Haskell packages and their versions you want to use.

π¦ base β standard Haskell library

π¦ containers β Map and Set data structures

π¦ text β efficient UTF-16 strings (UTF-8 since version 2.0)

π¦ bytestring β byte arrays

π¦ time β time, clocks and calendar data types and functions

π¦ aeson β JSON parsing

βΉοΈ Hackage has 16K+ packages

## Functional π½, Imperative π

readFile   :: FilePath -> IO Text
countWords :: Text -> IO (Map Text Int)
printWord  :: Map Text Int -> IO ()

π©βπ¬ Haskell allows controlling side effects. Separate pure logic from effectful computations and require IO only when needed.

βοΈ Write a program that finds the most frequent word in a file

π’ Imperative style

π€Έ Functional style

readFile      :: FilePath -> IO Text

countWords    :: Text -> Map Text Int
findFrequent  :: Map Text Int -> Maybe (Text, Int)
displayResult :: Maybe (Text, Int) -> Text

putStrLn      :: Text -> IO ()