diff --git a/monads/Makefile b/monads/Makefile index 1b05cce..666fc91 100644 --- a/monads/Makefile +++ b/monads/Makefile @@ -1,11 +1,8 @@ all: - make slide slideshow + make 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 - -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 + pandoc monads.md --filter pandoc-plot -f markdown-implicit_figures --pdf-engine=typst --template=template.typ -o monads.pdf view: zathura --mode=presentation monads.pdf & diff --git a/monads/monads.md b/monads/monads.md index 4dd3985..f061696 100644 --- a/monads/monads.md +++ b/monads/monads.md @@ -1,21 +1,23 @@ --- title: -- Monads +- Monads in Haskell author: - Sanchayan Maity -theme: -- default -classoption: -- aspectratio=169 +aspectratio: +- 169 +fontsize: +- 14pt +papersize: +- "presentation-16-9" --- -# Agenda +## Agenda - Recap of Functors - Recap of Applicative - Monads -# Functor[^1][^2] +## Functor ```haskell class Functor f where @@ -23,8 +25,6 @@ class Functor f where (<$) :: a -> f b -> f a ``` -Functors Laws - - Must preserve identity ```haskell @@ -37,16 +37,13 @@ fmap id = id fmap (f . g) == fmap f . fmap g ``` -[^1]: [Category Design Pattern](https://www.haskellforall.com/2012/08/the-category-design-pattern.html) -[^2]: [Functor Design Pattern](https://www.haskellforall.com/2012/09/the-functor-design-pattern.html) +## Higher order kinds -# 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 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 ``` -# Examples +## Examples ```haskell pure (+1) <*> [1..3] @@ -85,7 +82,7 @@ pure (+1) <*> [1..3] [(1,3),(1,4),(2,3),(2,4)] ``` -# Use cases[^4] +## Use cases ```haskell Person @@ -94,7 +91,7 @@ Person <*> parseTelephone "telephone" o ``` -Can also be written as +Can also be written as[^2] ```haskell liftA3 Person @@ -102,9 +99,9 @@ liftA3 Person (parseInt "age" 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 parsePerson :: Parser Person @@ -118,9 +115,7 @@ parsePerson = do pure $ Person name age ``` -[^5]: [FP Complete - Crash course to Applicative syntax](https://www.fpcomplete.com/haskell/tutorial/applicative-syntax/) - -# Use cases[^6] +## Use cases ```haskell helper :: () -> Text -> () -> () -> Int -> () -> Person @@ -136,10 +131,7 @@ parsePerson = helper <*> 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 @@ -153,7 +145,7 @@ liftA4 :: Applicative f => .. Where `liftA0 = pure` and `liftA1 = fmap`. -# Monoidal functors +## Monoidal functors - Remember Monoid? @@ -177,7 +169,7 @@ instance Monoid a => Applicative ((,) a) where (u, f) <*> (v, x) = (u `mappend` v, f x) ``` -# Where are monoids again +## Where are monoids again ```haskell fmap (+1) ("blah", 0) @@ -193,17 +185,15 @@ liftA2 (,) [1, 2] [3, 4] [(1,3),(1,4),(2,3),(2,4)] ``` -# Function apply +## Function apply - Applying a function to an `effectful` argument ```haskell (<$>) :: 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 -- Identity @@ -219,23 +209,26 @@ pure f <*> pure x = pure (f x) u <*> pure y = pure ($ y) <*> u ``` -# Operators[^7] +## Operators - `pure` wraps up a pure value into some kind of Applicative - `liftA2` applies a pure function to the values inside two `Applicative` wrapped values - `<$>` operator version of `fmap` - `<*>` 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%} -[^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 safeInverse :: Float -> Maybe Float @@ -251,7 +244,7 @@ sqrtInverse1 :: Float -> Maybe (Maybe Float) sqrtInverse1 x = safeInverse <$> (safeSqrt x) ``` -# Motivation - I +## Motivation - I ```haskell joinMaybe :: Maybe (Maybe a) -> Maybe a @@ -265,7 +258,7 @@ sqrtInverse2 x = joinMaybe $ safeInverse <$> (safeSqrt x) -- join :: Monad m => m (m a) -> m a ``` -# Motivation - II +## Motivation - II ```haskell (>>=) :: 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 ``` -# Motivation - III +## Motivation - III ```haskell (>=>) :: (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) ``` -# Motivations +## Motivations - Flattening - Sequencing - Composition -# Monad +## Monad ```haskell class Applicative m => Monad (m :: Type -> Type) where @@ -315,7 +308,7 @@ import Control.Monad (join) join :: Monad m => m (m a) -> m a ``` -# `do` notation +## Just **do** ```haskell main :: IO () @@ -326,7 +319,7 @@ main = do putStrLn greeting ``` -# Monad laws +## Monad laws ```haskell -- Left identity @@ -339,11 +332,11 @@ x >>= return == x m >>= (\x -> k x >>= h) == (m >>= k) >>= h ``` -# ??? +## ??? ![*_WTH_*](endofunctor.jpg){width=60%} -# Monoids recap +## Monoids recap ```haskell class Semigroup m where @@ -357,7 +350,7 @@ class Semigroup m => Monoid m where mappend = (<>) ``` -# Some Math +## Some Math ![*_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 - Two categories: **Set** and **Hask** -# Categories +## Categories - **Set** - Category of sets @@ -376,9 +369,9 @@ class Semigroup m => Monoid m where - Arrows between objects `a` & `b` are functions of type `a -> b` - `a -> b` also a `Type` 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 @@ -400,24 +393,24 @@ Type a -> m b ``` -# Now? +## Now? ![*_WTH_*](endofunctor2.jpg){width=80%} -# Contrasts with Monad +## Contrasts with Monad - No data dependency between `f a` and `f b` - Result of `f a` can't possibly influence the behaviour of `f b` - That needs something like `a -> f b` -# Applicative vs Monads +## Applicative vs Monads - Applicative * Effects * Batching and aggregation * Concurrency/Independent - 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 * Effects @@ -426,14 +419,14 @@ a -> m b - Parsing context sensitive grammar - Branching on previous results -# Weaker but better +## Weaker but better - Weaker than monads but thus also more common - 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 - No dependency issues or branching? just use applicative -# State monad +## State monad ```haskell newtype State s a = State { runState :: s -> (a, s) } @@ -452,7 +445,7 @@ instance Applicative (State s) where (aTob a, s'') ``` -# State monad +## State monad ```haskell instance Monad (State s) where @@ -473,7 +466,7 @@ get :: State s s get = State $ \s -> (s, s) ``` -# State monad +## State monad ```haskell put :: s -> State s () @@ -487,7 +480,7 @@ eval (State sa) x = let (a, _) = sa x in a ``` -# Context +## Context ```haskell type Stack = [Int] @@ -505,7 +498,7 @@ tos :: State Stack Int tos = State $ \(x:xs) -> (x, x:xs) ``` -# Context +## Context ```haskell stackManip :: State Stack Int @@ -520,7 +513,7 @@ stackManip = do testState = eval stackManip empty ``` -# Reader monad +## Reader monad ```haskell 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 ``` -# Context +## Context ```haskell import Control.Monad.Reader @@ -544,7 +537,7 @@ jerry = do return (env ++ " This is Jerry.") ``` -# Context +## Context ```haskell tomAndJerry :: Reader String String @@ -557,10 +550,8 @@ runJerryRun :: String runJerryRun = runReader tomAndJerry "Who is this?" ``` -# Questions +## Questions - Reach out on * Email: me@sanchayanmaity.net * Mastodon: [sanchayanmaity.com](https://sanchayanmaity.com/@sanchayan) - * Telegram: [t.me/SanchayanMaity](https://t.me/SanchayanMaity) - * Blog: [sanchayanmaity.net](https://sanchayanmaity.net/) diff --git a/monads/monads.pdf b/monads/monads.pdf index 3b23017..7f4bdb7 100644 Binary files a/monads/monads.pdf and b/monads/monads.pdf differ diff --git a/monads/style.tex b/monads/style.tex deleted file mode 100644 index 89d7670..0000000 --- a/monads/style.tex +++ /dev/null @@ -1 +0,0 @@ -\logo{\includegraphics[height=0.5cm]{../images/Haskell.jpg}\vspace{220pt}\hspace{8pt}} diff --git a/monads/template.typ b/monads/template.typ new file mode 100644 index 0000000..fad18c6 --- /dev/null +++ b/monads/template.typ @@ -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$