# Lecture 4

Monads and IO

# Monad: The Idea

## 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?

### 1. Nothing

### 2. Recognize

### 4. Abstract

### 5. Put in a library

### 3. Copy-paste

## Monad is a pattern

π **Monad** is a generalization of the "*andThen*" pattern

### How to generalize? π€

We need:

- Polymorphic
**andThen** - 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]))
```

## Monad

```
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

- Monad is a typeclass
- It has two methods
- The second method is an operator (it's called
**bind**) - It's a typeclass for
*type constructors*like**Maybe**and not e.g.**Int**

- Instances implemementations
- Laws
- How to use this abstraction efficiently
- Why it's called Monad

## Just a typeclass

## 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**

```
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

## Actually, in Haskell...

```
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 **FAM**ily

π©βπ¬ Everyone uses **pure** instead of **return** nowadays

## And that's the Monad!

# Real World

## Purity π§

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

π **Pure** **functions** β functions without side-effects that depend only on their explicit input arguments.

### π₯ Benefits of pure functions

### 1. Determinism

### 4. Composability

### 2. Easier reasoning

### 5. Optimizations

### 6. Parallelism

### 3. Simpler testing

## π§ Purity + Laziness π¦₯

`getLine :: String`

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

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

π€π€ How about reading two lines??

```
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
...
```

π©βπ¬ The **Monad** instance for **IO** allows to chain effectful actions

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

## Common question

### How to get String from IO String?

## 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!"
```

### 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
```

π Classic Monad Style

### βοΈ Common mistake #1

`let line = getLine`

`rev <- reverse line`

### βοΈ Common mistake #2

π **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
```

π A Haskell package

π 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.

### Common Haskell packages

π¦ 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 ()
```

## More sources

#### Lecture 4: Monads and IO

By Haskell Beginners 2022

# Lecture 4: Monads and IO

Fundamentals of Functional Programming and Haskell

- 2,781