Use typst for monads presentation

This commit is contained in:
Sanchayan Maity 2024-11-21 20:53:06 +05:30
parent 2031c13030
commit 60b7f9e152
5 changed files with 192 additions and 74 deletions

View file

@ -1,11 +1,8 @@
all: all:
make slide slideshow make slide
slide: slide:
pandoc -t beamer --include-in-header=./style.tex monads.md -f markdown-implicit_figures -V colorlinks=true -V linkcolor=blue -V urlcolor=red -o monads.pdf pandoc monads.md --filter pandoc-plot -f markdown-implicit_figures --pdf-engine=typst --template=template.typ -o monads.pdf
slideshow:
pandoc -t beamer --include-in-header=./style.tex monads.md -f markdown-implicit_figures -V colorlinks=true -V linkcolor=blue -V urlcolor=red -i -o monads-slideshow.pdf
view: view:
zathura --mode=presentation monads.pdf & zathura --mode=presentation monads.pdf &

View file

@ -1,21 +1,23 @@
--- ---
title: title:
- Monads - Monads in Haskell
author: author:
- Sanchayan Maity - Sanchayan Maity
theme: aspectratio:
- default - 169
classoption: fontsize:
- aspectratio=169 - 14pt
papersize:
- "presentation-16-9"
--- ---
# Agenda ## Agenda
- Recap of Functors - Recap of Functors
- Recap of Applicative - Recap of Applicative
- Monads - Monads
# Functor[^1][^2] ## Functor
```haskell ```haskell
class Functor f where class Functor f where
@ -23,8 +25,6 @@ class Functor f where
(<$) :: a -> f b -> f a (<$) :: a -> f b -> f a
``` ```
Functors Laws
- Must preserve identity - Must preserve identity
```haskell ```haskell
@ -37,16 +37,13 @@ fmap id = id
fmap (f . g) == fmap f . fmap g fmap (f . g) == fmap f . fmap g
``` ```
[^1]: [Category Design Pattern](https://www.haskellforall.com/2012/08/the-category-design-pattern.html) ## Higher order kinds
[^2]: [Functor Design Pattern](https://www.haskellforall.com/2012/09/the-functor-design-pattern.html)
# Higher order kinds[^3] - For something to be a functor, it has to be a first order kind[^1].
- For something to be a functor, it has to be a first order kind. [^1]: [Haskell's Kind System](https://diogocastro.com/blog/2018/10/17/haskells-kind-system-a-primer/)
[^3]: [Haskell's Kind System](https://diogocastro.com/blog/2018/10/17/haskells-kind-system-a-primer/) ## Applicative
# Applicative
```haskell ```haskell
class Functor f => Applicative (f :: TYPE -> TYPE) where class Functor f => Applicative (f :: TYPE -> TYPE) where
@ -63,7 +60,7 @@ class Functor f => Applicative (f :: TYPE -> TYPE) where
fmap f x = pure f <*> x fmap f x = pure f <*> x
``` ```
# Examples ## Examples
```haskell ```haskell
pure (+1) <*> [1..3] pure (+1) <*> [1..3]
@ -85,7 +82,7 @@ pure (+1) <*> [1..3]
[(1,3),(1,4),(2,3),(2,4)] [(1,3),(1,4),(2,3),(2,4)]
``` ```
# Use cases[^4] ## Use cases
```haskell ```haskell
Person Person
@ -94,7 +91,7 @@ Person
<*> parseTelephone "telephone" o <*> parseTelephone "telephone" o
``` ```
Can also be written as Can also be written as[^2]
```haskell ```haskell
liftA3 Person liftA3 Person
@ -102,9 +99,9 @@ liftA3 Person
(parseInt "age" o) (parseInt "age" o)
(parseTelephone "telephone" o) (parseTelephone "telephone" o)
``` ```
[^4]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/) [^2]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/)
# Use cases[^5] ## Use cases
```haskell ```haskell
parsePerson :: Parser Person parsePerson :: Parser Person
@ -118,9 +115,7 @@ parsePerson = do
pure $ Person name age pure $ Person name age
``` ```
[^5]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/) ## Use cases
# Use cases[^6]
```haskell ```haskell
helper :: () -> Text -> () -> () -> Int -> () -> Person helper :: () -> Text -> () -> () -> Int -> () -> Person
@ -136,10 +131,7 @@ parsePerson = helper
<*> endOfLine <*> endOfLine
``` ```
[^6]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/) ## Lifting
# Lifting
- Seeing Functor as unary lifting and Applicative as n-ary lifting - Seeing Functor as unary lifting and Applicative as n-ary lifting
@ -153,7 +145,7 @@ liftA4 :: Applicative f => ..
Where `liftA0 = pure` and `liftA1 = fmap`. Where `liftA0 = pure` and `liftA1 = fmap`.
# Monoidal functors ## Monoidal functors
- Remember Monoid? - Remember Monoid?
@ -177,7 +169,7 @@ instance Monoid a => Applicative ((,) a) where
(u, f) <*> (v, x) = (u `mappend` v, f x) (u, f) <*> (v, x) = (u `mappend` v, f x)
``` ```
# Where are monoids again ## Where are monoids again
```haskell ```haskell
fmap (+1) ("blah", 0) fmap (+1) ("blah", 0)
@ -193,17 +185,15 @@ liftA2 (,) [1, 2] [3, 4]
[(1,3),(1,4),(2,3),(2,4)] [(1,3),(1,4),(2,3),(2,4)]
``` ```
# Function apply ## Function apply
- Applying a function to an `effectful` argument - Applying a function to an `effectful` argument
```haskell ```haskell
(<$>) :: Functor m => (a -> b) -> m a -> m b (<$>) :: Functor m => (a -> b) -> m a -> m b
(<*>) :: Applicative m => m (a -> b) -> m a -> m b
(=<<) :: Monad m => (a -> m b) -> m a -> m b
``` ```
# Applicative laws ## Applicative laws
```haskell ```haskell
-- Identity -- Identity
@ -219,23 +209,26 @@ pure f <*> pure x = pure (f x)
u <*> pure y = pure ($ y) <*> u u <*> pure y = pure ($ y) <*> u
``` ```
# Operators[^7] ## Operators
- `pure` wraps up a pure value into some kind of Applicative - `pure` wraps up a pure value into some kind of Applicative
- `liftA2` applies a pure function to the values inside two `Applicative` wrapped values - `liftA2` applies a pure function to the values inside two `Applicative` wrapped values
- `<$>` operator version of `fmap` - `<$>` operator version of `fmap`
- `<*>` apply a wrapped function to a wrapped value - `<*>` apply a wrapped function to a wrapped value
- `*>`, `<*` - `*>`, `<*`
- See more at[^3]
[^7]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/) [^3]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/)
# Monad, is that you?[^8] ## Monad, is that you?
![*_Monads_*](burrito-monad.png){width=60%} ![*_Monads_*](burrito-monad.png){width=60%}
[^8]: [The Unreasonable Effectiveness of Metaphor](https://argumatronic.com/posts/2018-09-02-effective-metaphor.html) - Unreasonable Effectiveness of Metaphor[^4]
# Motivation - I [^4]: [The Unreasonable Effectiveness of Metaphor](https://argumatronic.com/posts/2018-09-02-effective-metaphor.html)
## Motivation - I
```haskell ```haskell
safeInverse :: Float -> Maybe Float safeInverse :: Float -> Maybe Float
@ -251,7 +244,7 @@ sqrtInverse1 :: Float -> Maybe (Maybe Float)
sqrtInverse1 x = safeInverse <$> (safeSqrt x) sqrtInverse1 x = safeInverse <$> (safeSqrt x)
``` ```
# Motivation - I ## Motivation - I
```haskell ```haskell
joinMaybe :: Maybe (Maybe a) -> Maybe a joinMaybe :: Maybe (Maybe a) -> Maybe a
@ -265,7 +258,7 @@ sqrtInverse2 x = joinMaybe $ safeInverse <$> (safeSqrt x)
-- join :: Monad m => m (m a) -> m a -- join :: Monad m => m (m a) -> m a
``` ```
# Motivation - II ## Motivation - II
```haskell ```haskell
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
@ -282,7 +275,7 @@ sqrtInverse x = (>>=) (safeSqrt x) safeInverse
-- (>>=) :: Monad m => m a -> (a -> m b) -> m b -- (>>=) :: Monad m => m a -> (a -> m b) -> m b
``` ```
# Motivation - III ## Motivation - III
```haskell ```haskell
(>=>) :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c) (>=>) :: (a -> Maybe b) -> (b -> Maybe c) -> (a -> Maybe c)
@ -297,13 +290,13 @@ sqrtInverse3 = safeSqrt >=> safeInverse
-- (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c) -- (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
``` ```
# Motivations ## Motivations
- Flattening - Flattening
- Sequencing - Sequencing
- Composition - Composition
# Monad ## Monad
```haskell ```haskell
class Applicative m => Monad (m :: Type -> Type) where class Applicative m => Monad (m :: Type -> Type) where
@ -315,7 +308,7 @@ import Control.Monad (join)
join :: Monad m => m (m a) -> m a join :: Monad m => m (m a) -> m a
``` ```
# `do` notation ## Just **do**
```haskell ```haskell
main :: IO () main :: IO ()
@ -326,7 +319,7 @@ main = do
putStrLn greeting putStrLn greeting
``` ```
# Monad laws ## Monad laws
```haskell ```haskell
-- Left identity -- Left identity
@ -339,11 +332,11 @@ x >>= return == x
m >>= (\x -> k x >>= h) == (m >>= k) >>= h m >>= (\x -> k x >>= h) == (m >>= k) >>= h
``` ```
# ??? ## ???
![*_WTH_*](endofunctor.jpg){width=60%} ![*_WTH_*](endofunctor.jpg){width=60%}
# Monoids recap ## Monoids recap
```haskell ```haskell
class Semigroup m where class Semigroup m where
@ -357,7 +350,7 @@ class Semigroup m => Monoid m where
mappend = (<>) mappend = (<>)
``` ```
# Some Math ## Some Math
![*_Morphism_*](morphism.png){width=30%} ![*_Morphism_*](morphism.png){width=30%}
@ -365,7 +358,7 @@ class Semigroup m => Monoid m where
- Arrows between objects (morphisms): functions mapping one object to another - Arrows between objects (morphisms): functions mapping one object to another
- Two categories: **Set** and **Hask** - Two categories: **Set** and **Hask**
# Categories ## Categories
- **Set** - **Set**
- Category of sets - Category of sets
@ -376,9 +369,9 @@ class Semigroup m => Monoid m where
- Arrows between objects `a` & `b` are functions of type `a -> b` - Arrows between objects `a` & `b` are functions of type `a -> b`
- `a -> b` also a `Type` in **Hask** - `a -> b` also a `Type` in **Hask**
- If `A -> B` and `B -> C`, then `A -> C` ~= `.` in **Hask** - If `A -> B` and `B -> C`, then `A -> C` ~= `.` in **Hask**
- Fun fact: Function composition forms a monoid! (See [Endo](https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-Monoid.html#t:Endo)). - Fun fact: Function composition forms a monoid! (See [Endo](https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-Monoid.html##t:Endo)).
# Monads are monoids... ## Monads are monoids...
In Haskell In Haskell
@ -400,24 +393,24 @@ Type
a -> m b a -> m b
``` ```
# Now? ## Now?
![*_WTH_*](endofunctor2.jpg){width=80%} ![*_WTH_*](endofunctor2.jpg){width=80%}
# Contrasts with Monad ## Contrasts with Monad
- No data dependency between `f a` and `f b` - No data dependency between `f a` and `f b`
- Result of `f a` can't possibly influence the behaviour of `f b` - Result of `f a` can't possibly influence the behaviour of `f b`
- That needs something like `a -> f b` - That needs something like `a -> f b`
# Applicative vs Monads ## Applicative vs Monads
- Applicative - Applicative
* Effects * Effects
* Batching and aggregation * Batching and aggregation
* Concurrency/Independent * Concurrency/Independent
- Parsing context free grammar - Parsing context free grammar
- Exploring all branches of computation (see [`Alternative`](https://hackage.haskell.org/package/base-4.20.0.1/docs/Control-Applicative.html#t:Alternative)) - Exploring all branches of computation (see [`Alternative`](https://hackage.haskell.org/package/base-4.20.0.1/docs/Control-Applicative.html##t:Alternative))
- Monads - Monads
* Effects * Effects
@ -426,14 +419,14 @@ a -> m b
- Parsing context sensitive grammar - Parsing context sensitive grammar
- Branching on previous results - Branching on previous results
# Weaker but better ## Weaker but better
- Weaker than monads but thus also more common - Weaker than monads but thus also more common
- Lends itself to optimisation (See Facebook's [Haxl](https://hackage.haskell.org/package/haxl) project) - Lends itself to optimisation (See Facebook's [Haxl](https://hackage.haskell.org/package/haxl) project)
- Always opt for the least powerful mechanism to get things done - Always opt for the least powerful mechanism to get things done
- No dependency issues or branching? just use applicative - No dependency issues or branching? just use applicative
# State monad ## State monad
```haskell ```haskell
newtype State s a = State { runState :: s -> (a, s) } newtype State s a = State { runState :: s -> (a, s) }
@ -452,7 +445,7 @@ instance Applicative (State s) where
(aTob a, s'') (aTob a, s'')
``` ```
# State monad ## State monad
```haskell ```haskell
instance Monad (State s) where instance Monad (State s) where
@ -473,7 +466,7 @@ get :: State s s
get = State $ \s -> (s, s) get = State $ \s -> (s, s)
``` ```
# State monad ## State monad
```haskell ```haskell
put :: s -> State s () put :: s -> State s ()
@ -487,7 +480,7 @@ eval (State sa) x = let (a, _) = sa x
in a in a
``` ```
# Context ## Context
```haskell ```haskell
type Stack = [Int] type Stack = [Int]
@ -505,7 +498,7 @@ tos :: State Stack Int
tos = State $ \(x:xs) -> (x, x:xs) tos = State $ \(x:xs) -> (x, x:xs)
``` ```
# Context ## Context
```haskell ```haskell
stackManip :: State Stack Int stackManip :: State Stack Int
@ -520,7 +513,7 @@ stackManip = do
testState = eval stackManip empty testState = eval stackManip empty
``` ```
# Reader monad ## Reader monad
```haskell ```haskell
class Monad m => MonadReader r m | m -> r where class Monad m => MonadReader r m | m -> r where
@ -528,7 +521,7 @@ class Monad m => MonadReader r m | m -> r where
local :: (r -> r) -> m a -> m a local :: (r -> r) -> m a -> m a
``` ```
# Context ## Context
```haskell ```haskell
import Control.Monad.Reader import Control.Monad.Reader
@ -544,7 +537,7 @@ jerry = do
return (env ++ " This is Jerry.") return (env ++ " This is Jerry.")
``` ```
# Context ## Context
```haskell ```haskell
tomAndJerry :: Reader String String tomAndJerry :: Reader String String
@ -557,10 +550,8 @@ runJerryRun :: String
runJerryRun = runReader tomAndJerry "Who is this?" runJerryRun = runReader tomAndJerry "Who is this?"
``` ```
# Questions ## Questions
- Reach out on - Reach out on
* Email: me@sanchayanmaity.net * Email: me@sanchayanmaity.net
* Mastodon: [sanchayanmaity.com](https://sanchayanmaity.com/@sanchayan) * Mastodon: [sanchayanmaity.com](https://sanchayanmaity.com/@sanchayan)
* Telegram: [t.me/SanchayanMaity](https://t.me/SanchayanMaity)
* Blog: [sanchayanmaity.net](https://sanchayanmaity.net/)

Binary file not shown.

View file

@ -1 +0,0 @@
\logo{\includegraphics[height=0.5cm]{../images/Haskell.jpg}\vspace{220pt}\hspace{8pt}}

131
monads/template.typ Normal file
View file

@ -0,0 +1,131 @@
#import "@preview/diatypst:0.2.0": *
#show: slides.with(
title: "Monads in Haskell",
authors: ("Sanchayan Maity"),
ratio: 16/9,
layout: "large",
toc: false,
footer: false,
count: true,
)
$definitions.typst()$
#show terms: it => {
it.children
.map(child => [
#strong[#child.term]
#block(inset: (left: 1.5em, top: -0.4em))[#child.description]
])
.join()
}
#set table(
inset: 6pt,
stroke: none
)
#show figure.where(
kind: table
): set figure.caption(position: $if(table-caption-position)$$table-caption-position$$else$top$endif$)
#show figure.where(
kind: image
): set figure.caption(position: $if(figure-caption-position)$$figure-caption-position$$else$bottom$endif$)
$if(template)$
#import "$template$": conf
$else$
$template.typst()$
$endif$
$for(header-includes)$
$header-includes$
$endfor$
#show: doc => conf(
$if(title)$
title: [$title$],
$endif$
$if(subtitle)$
subtitle: [$subtitle$],
$endif$
$if(author)$
authors: (
$for(author)$
$if(author.name)$
( name: [$author.name$],
affiliation: [$author.affiliation$],
email: [$author.email$] ),
$else$
( name: [$author$],
affiliation: "",
email: "" ),
$endif$
$endfor$
),
$endif$
$if(keywords)$
keywords: ($for(keywords)$$keyword$$sep$,$endfor$),
$endif$
$if(date)$
date: [$date$],
$endif$
$if(lang)$
lang: "$lang$",
$endif$
$if(region)$
region: "$region$",
$endif$
$if(abstract)$
abstract: [$abstract$],
$endif$
$if(margin)$
margin: ($for(margin/pairs)$$margin.key$: $margin.value$,$endfor$),
$endif$
$if(papersize)$
paper: "$papersize$",
$endif$
$if(mainfont)$
font: ("$mainfont$",),
$endif$
$if(fontsize)$
fontsize: $fontsize$,
$endif$
$if(section-numbering)$
sectionnumbering: "$section-numbering$",
$endif$
cols: $if(columns)$$columns$$else$1$endif$,
doc,
)
$for(include-before)$
$include-before$
$endfor$
$if(toc)$
#outline(
title: auto,
depth: $toc-depth$
);
$endif$
$body$
$if(citations)$
$if(csl)$
#set bibliography(style: "$csl$")
$elseif(bibliographystyle)$
#set bibliography(style: "$bibliographystyle$")
$endif$
$if(bibliography)$
#bibliography($for(bibliography)$"$bibliography$"$sep$,$endfor$)
$endif$
$endif$
$for(include-after)$
$include-after$
$endfor$