SlideShare una empresa de Scribd logo
1 de 84
Descargar para leer sin conexión
Build Your Own Monads
LambdaWorld 2018, Cadiz
Alejandro Serrano Mena
0
Welcome!
What are we going to do here?
• Understand why custom monads are useful
• Learn the different elements in a custom monad
• Practice how to create them in various styles
• Final tagless / MTL style
• Initial style / Free monads
1
What are we going to do here?
• Understand why custom monads are useful
• Learn the different elements in a custom monad
• Practice how to create them in various styles
• Final tagless / MTL style
• Initial style / Free monads
Talk! Think! Code!
1
Who am I?
Alejandro / @trupill in Twitter / @serras in GitHub
• Associate Professor at Utrecht University, NL
• Teacher of FP courses at various levels
• Researcher on FP topics, mostly Haskell
• Writer of books about Haskell
• Beginning Haskell, published by Apress
• The Book of Monads, to appear soon
• Advocate of strong typing in programming languages
• Haskell, Agda, Idris, LiquidHaskell, …
• Secretly in love with Lisp and macros
2
Talk! Think! Code!
As part of the workshop, we discuss some exercises
• Work together with your neighbour!
• 5-7 minutes work + 5-7 minutes discussion
Some (but not all) exercises involve coding
• Haskell? Scala? Whitespace? I don’t care!
• Your language must support higher-kinded abstraction
Prerequisite: some experience with monads
3
Why custom monads?
The path to monads
1. Discover the most common monads
• State, Maybe, Reader, Writer…
2. Learn operations shared among them
• mapM, sequence, …
3. Work hard when you require several of them
• Usually using monad transformers
4
Benefits
• Common operations
• Once again, mapM, sequence, …
• Functor, Applicative, Traversable
• Compiler support
• do notation, for comprehensions
• Well-known set of primitive blocks
5
The truth
These monads take you a long way
6
The truth
These monads take you a long way
Why bother then?
6
The truth
These monads take you a long way
Why bother then?
Abstraction and Safety
6
Abstraction
Capture your domain better
FP provides powerful tools to capture data and their invariants
• Algebraic data types and pattern matching
• Strong type systems
• Contracts for dynamically-typed languages
What about processes / services?
7
Abstraction
Capture your domain better
FP provides powerful tools to capture data and their invariants
• Algebraic data types and pattern matching
• Strong type systems
• Contracts for dynamically-typed languages
What about processes / services?
Custom monads!
7
My domain: Tic-Tac-Toe
• Query the state of the board
data Position = Position ...
data Player = O | X deriving (Eq, Ord)
info :: Position -> TicTacToe (Maybe Player)
• Indicate that we want to claim an empty position
• Know whether we have already won or lost
data Result = AlreadyTaken { by :: Player }
| NextTurn
| GameEnded { winner :: Player }
take :: Position -> TicTacToe Result
8
Safety
Ensure that only a subset of operations of a big monad is
available in a certain computation
• Usually, the big monad is IO
Some examples:
• Talk only to the database
• Restrict console output to logging
9
Abstraction or Safety?
10
Abstraction or Safety?
We ♡ Both!
10
Time to think #1
Talk to each other and find:
• Example of a domain to model
• Processes or services in that domain
• Not too complicated, few primitives
11
Syntax and Semantics
Syntax and Semantics
In our custom monads we usually separate:
• The description of computations
• Including the available primitives
• From the execution of the computations
In State, Maybe, … those are intertwined
12
Syntax / Algebra
1. Primitive operations for your monad
2. Combinators to describe computations
• In addition to the monadic ones
In summary, how to describe behaviors in your domain
13
Syntax / Algebra
1. Primitive operations for your monad
2. Combinators to describe computations
• In addition to the monadic ones
In summary, how to describe behaviors in your domain
“API” for your monad
info :: Position -> TicTacToe (Maybe Player)
take :: Position -> TicTacToe Result
13
Semantics / Interpretations / Handlers
Execute the computations describes by the syntax
• Usually mapping each primitive to an action
14
Semantics / Interpretations / Handlers
Execute the computations describes by the syntax
• Usually mapping each primitive to an action
More than one interpretation is possible
For example, for our TicTacToe monad
• Run with console IO
• Run on a graphical UI over a network
• Mock execution for tests
14
Time to think #2
Consider the domain from the first exercise and:
• Make the syntax more concrete
• Give an API for your primitives
• Think of a derived operation using those primitives
• Describe one or more interpretations
15
Implementing custom monads
Three different styles
• Final style / Object algebras / MTL style
• Initial style
• Pattern abstracted into free monads
• Operational style
• Pattern abstracted into freer monads
16
Three different styles
• Final style / Object algebras / MTL style
• Initial style
• Pattern abstracted into free monads
• Operational style
• Pattern abstracted into freer monads
Initial and operational are fairly similar
16
Three different styles
For each of the style we need to say how to:
1. Define the syntax of the monad
2. Give a nicer syntax for the API, if required
3. Write computations and which type they get
4. Define interpretations
17
Quick summary
Final style = Type classes
Initial style = Data type with continuations
18
Monads in final style
Final style: syntax
Use a type class or a trait
• Each primitive operation is a method in the class
• Positions where the monad would appear are replaced by
the variable heading the class
class TicTacToe m where
info :: Position -> m (Maybe Player)
take :: Position -> m Result
trait TicTacToe[F[_]] {
def info(p: Position): F[Option[Player]]
def take(p: Position): F[Result]
}
19
Final style: computations
Simply use the monad combinators and the primitives
takeIfNotTaken p = do
i <- info p
case i of
Just _ -> return Nothing
Nothing -> Just <$> take p
20
Final style: computations
Simply use the monad combinators and the primitives
takeIfNotTaken p = do
i <- info p
case i of
Just _ -> return Nothing
Nothing -> Just <$> take p
The type reflects that you need a monad which supports the
TicTacToe operations
takeIfNotTaken :: (Monad m, TicTacToe m)
=> Position -> m (Maybe Result)
20
Why keep Monad separate from TicTacToe?
Another possibility, closer to the mtl library:
class Monad m => TicTacToe m where
info :: Position -> m (Maybe Player)
take :: Position -> m Result
21
Why keep Monad separate from TicTacToe?
Another possibility, closer to the mtl library:
class Monad m => TicTacToe m where
info :: Position -> m (Maybe Player)
take :: Position -> m Result
As a result, computations get a “cleaner” type:
takeIfNotTaken :: TicTacToe m -- No Monad m
=> Position -> m (Maybe Result)
21
Why keep Monad separate from TicTacToe?
Another possibility, closer to the mtl library:
class Monad m => TicTacToe m where
info :: Position -> m (Maybe Player)
take :: Position -> m Result
As a result, computations get a “cleaner” type:
takeIfNotTaken :: TicTacToe m -- No Monad m
=> Position -> m (Maybe Result)
Personally, I prefer to keep them separate:
• Sometimes Applicative is enough
• But with this approach Monad infects everything
21
Final style: interpretations
Each interpretation is an instance of the type class
type Board = Map Position Player
type RPSBI = ReaderT Player (StateT Board IO)
instance TicTacToe RPSBI where
info p = lookup p <$> get
take p = do
l <- info p
case l of
Just p' -> return AlreadyTaken { by = p' }
Nothing -> do me <- ask
modify (insert p me)
liftIO (putStrLn "Your next move:")
... 22
Final style: interpretations
For “safety” monads we map into the larger monad
class Logging m where
log :: String -> m ()
instance Logging IO where
log = putStrLn
23
Final style: interpretations
For “safety” monads we map into the larger monad
class Logging m where
log :: String -> m ()
instance Logging IO where
log = putStrLn
Q: what is the implementation of…?
run :: (forall m. Logging m => m a) -> IO a
23
Final style: interpretations
For “safety” monads we map into the larger monad
class Logging m where
log :: String -> m ()
instance Logging IO where
log = putStrLn
Q: what is the implementation of…?
run :: (forall m. Logging m => m a) -> IO a
run x = x
23
Time to code #3
Implement your monad in final style:
• Define the type class or trait
• Implement the derived operation from #2
• Sketch an interpretation
24
Monads in initial style
Initial style: syntax
Use a data type with continuations
• For each primitive operation op :: A -> B -> ... -> M Z
• Create a new constructor in the data type
• Add fields of types A, B, …
• The last argument is a function Z -> M a which refers back
to the monad (that is, a continuation)
• Also, we have a constructor with a single field a
• Represents the return of the monad
25
Initial style: example
The primitive operations of our TicTacToe monad:
info :: Position -> TicTacToe (Maybe Player)
take :: Position -> TicTacToe Result
26
Initial style: example
The primitive operations of our TicTacToe monad:
info :: Position -> TicTacToe (Maybe Player)
take :: Position -> TicTacToe Result
The TicTacToe data type is defined as:
data TicTacToe a
= Info Position (Maybe Player -> TicTacToe a)
| Take Position (Result -> TicTacToe a)
| Done a
In Scala the code would be slightly longer…
26
Is this thing even a Monad?
Let’s build it step by step using GHC holes…
27
Is this thing even a Monad?
This is the final result:
instance Monad TicTacToe where
return = Done
(Done x) >>= f = f x
(Info p k) >>= f = Info p (pl -> k pl >>= f)
(Take p k) >>= f = Take p (r -> k r >>= f)
28
Reminder of a computation in final style
takeIfNotTaken p = do
i <- info p
case i of
Just _ -> return Nothing
Nothing -> Just <$> take p
How would this look in initial style?
29
Initial style: computations
takeIfNotTaken p = do
i <- info p
case i of
Just _ -> return Nothing
Nothing -> Just <$> take p
We have to deal with continuations ourselves
• Without any help of do notation
takeIfNotTaken p =
Info p $ i ->
case i of
Just _ -> Done Nothing
Nothing -> Take p $ r -> Done (Just r)
30
Initial style: smart constructors
This is a trick to get versions of the primitive operations which
we can combine using do notation
31
Initial style: smart constructors
This is a trick to get versions of the primitive operations which
we can combine using do notation
This is what we have:
Info :: Position -> (Maybe Player -> TicTacToe a)
-> TicTacToe a
and this is what we want as our API:
info :: Position -> TicTacToe (Maybe Player)
31
Initial style: smart constructors
This is a trick to get versions of the primitive operations which
we can combine using do notation
This is what we have:
Info :: Position -> (Maybe Player -> TicTacToe a)
-> TicTacToe a
and this is what we want as our API:
info :: Position -> TicTacToe (Maybe Player)
info p = Info p return
-- return :: Maybe Player -> TicTacToe (Maybe Player)
31
Initial style: interpretations
Interpretations are usually (but not always) natural
transformations from our custom monad to another monad
runGame :: TicTacToe a -> RPSBI a
def runGame :: TicTacToe ~> RPSBI
32
Initial style: interpretations
Interpretations are usually (but not always) natural
transformations from our custom monad to another monad
runGame :: TicTacToe a -> RPSBI a
def runGame :: TicTacToe ~> RPSBI
runGame (Done x) = return x
runGame (Info p k) = do pl <- lookup p <$> get
runGame (k pl)
runGame (Take p k) = do pl <- lookup p <$> get
case pl of
Just p' ->
runGame (k $ AlreadyTaken p')
Nothing -> ...
32
Continuations in interpretations
Note the similarities between the two operations:
runGame (Info p k) = do ...
runGame (k pl)
runGame (Take p k) = do ...
runGame (k $ AlreadyTaken p')
Always the last line on each branch:
• Calls the continuations with some data
• Recursively calls runGame
33
Time to code #4
Implement your monad in initial style:
• Define the corresponding data type and its Monad instance
• Implement the derived operation from #2 using
continuations manually
• Write the smart constructor for each primitive and
implement the derived operation again
34
Free monads
All initial style monads are created equal
• The data type always has a constructor for return
• The other constructors follow a similar shape
• Smart constructors are obtained by using return as the
continuation
• Interpretations into other monads have the same
recursive structure
35
All initial style monads are created equal
• The data type always has a constructor for return
• The other constructors follow a similar shape
• Smart constructors are obtained by using return as the
continuation
• Interpretations into other monads have the same
recursive structure
How to abstract these commonalities? Free monads!
35
Free monads: warning
My notion of free monads abstract over initial style
• Implemented in Haskell’s free package
• Corresponds to the categorical notion of free monad of a
functor
Scalaz and Cats Free abstract over operational style
• In Haskell this is known as the freer monad and can be
found in the operational package
• Very similar, and easier to use
36
Separate the common from the specific
data TicTacToe a
= Info Position (Maybe Player -> TicTacToe a)
| Take Position (Result -> TicTacToe a)
| Done a
-- Specific to TicTacToe
data TicTacToeF r
= Info Position (Maybe Player -> r)
| Take Position (Result -> r)
-- Common to all initial style monads
data Free f a
= Free (f (Free f a))
| Pure a
-- All together now
type TicTacToe = Free TicTacToeF 37
Free monad of a functor
Let us have a peek into the Monad instance of Free
instance Functor f => Monad (Free f) where
return = Pure
Pure x >>= f = f x
Free x >>= f = Free (fmap (>>= f) x)
So we need TicTacToeF to be a functor!
38
Free monad of a functor
Let us have a peek into the Monad instance of Free
instance Functor f => Monad (Free f) where
return = Pure
Pure x >>= f = f x
Free x >>= f = Free (fmap (>>= f) x)
So we need TicTacToeF to be a functor!
• These data types are always functors
• GHC can derive the Functor instance for us
data TicTacToeF r = ... deriving Functor
38
Smart constructors for free monads
Now what we have is slightly different:
Info :: Position -> (Maybe Player -> r)
-> TicTacToeF r
And also what we want to achieve:
info :: Position -> Free TicTacToeF (Maybe Player)
39
Smart constructors for free monads
Now what we have is slightly different:
Info :: Position -> (Maybe Player -> r)
-> TicTacToeF r
And also what we want to achieve:
info :: Position -> Free TicTacToeF (Maybe Player)
info p = Free _
-- _ has type
-- TicTacToeF (Free TicTacToeF (Maybe Player))
39
Smart constructors for free monads
Now what we have is slightly different:
Info :: Position -> (Maybe Player -> r)
-> TicTacToeF r
And also what we want to achieve:
info :: Position -> Free TicTacToeF (Maybe Player)
info p = Free (Info p _)
-- _ has type
-- (Maybe Player -> Free TicTacToeF (Maybe Player))
40
Smart constructors for free monads
Now what we have is slightly different:
Info :: Position -> (Maybe Player -> r)
-> TicTacToeF r
And also what we want to achieve:
info :: Position -> Free TicTacToeF (Maybe Player)
info p = Free (Info p return)
-- Almost as before!
-- :)
41
Interpretations for free monads
We only need to provide the specifics of each operation:
runGame' :: TicTacToeF a -> RPSBI a
runGame' (Info p k) = do pl <- lookup p <$> get
return (k pl)
runGame' (Take p k) = ...
42
Interpretations for free monads
We only need to provide the specifics of each operation:
runGame' :: TicTacToeF a -> RPSBI a
runGame' (Info p k) = do pl <- lookup p <$> get
return (k pl)
runGame' (Take p k) = ...
The recursive part is tied using foldFree:
foldFree :: Monad m => (forall r. f r -> m r)
-> Free f a -> m a
foldFree _ (Pure x) = return x
foldFree f (Free x) = f x >>= foldFree f
runGame = foldFree runGame'
42
Time to code #5
Rewrite your initial style monad as a free monad
• Define the functor for your primitives
• Rewrite the smart constructors
• Enjoy the reduction in lines!
43
What is missing?
Combining several monads
Final style monads are very easy to combine
fileAndNetwork :: (Monad m, FS m, Network m)
=> URL -> FilePath -> m Result
44
Combining several monads
Final style monads are very easy to combine
fileAndNetwork :: (Monad m, FS m, Network m)
=> URL -> FilePath -> m Result
Initial style monads are impossible to combine
• But we can combine them if they are free monads
fileAndNetwork :: URL -> FilePath
-> Free (FSF :+: NetworkF) Result
44
Combining functors
The technique used to combine the operations from two
functors is called Data types à la carte
data (f :+: g) a = InL (f a) | InR (g a)
Although getting good syntax is more complicated
45
Performance
Peformance of free monads degrades with left-nested binds
• Akin to the problem of left-nested concatenation in lists
46
Performance
Peformance of free monads degrades with left-nested binds
• Akin to the problem of left-nested concatenation in lists
Several solutions have been proposed:
• Church and Scott encodings
• Codensity transformation
• Type-aligned sequences / “Reflection without Remorse”
But there is no clear winner for all cases
46
Summary
• Custom monads help us modelling behaviors in our
domain
• There are several styles to build them
• Final: using type classes
• Initial: using data types
• Free monads abstract the commonalities
• Operational: not treated today
47
Thank you!
Feel free to ask me anything during the rest of
LambdaWorld
48
Thank you!
Feel free to ask me anything during the rest of
LambdaWorld
Let’s go for lunch!
48
Additional slides
Why “MTL style”?
MTL = Monad Transformer Library
• Supports working with monad stacks polymorphically
• Defines classes MonadState, MonadReader, and so on
• Programmers may mix primitives from several monads in
one computation
increaseAndLog :: (MonadState Int m, MonadWriter String m)
=> Int -> m Int
increaseAndLog n = do
s <- get
let new = s + n
put new
tell $ "New value: " ++ show new ++ "n"
49
Smart constructors, generically
The free package provides another combinator:
liftF :: Functor f => f a -> Free f a
liftF = Free . fmap return
Using liftF you can write instead:
info p = liftF (Info p id)
50

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

Acm aleppo cpc training second session
Acm aleppo cpc training second sessionAcm aleppo cpc training second session
Acm aleppo cpc training second session
 
Python Basics
Python Basics Python Basics
Python Basics
 
06.Loops
06.Loops06.Loops
06.Loops
 
Python Tutorial
Python TutorialPython Tutorial
Python Tutorial
 
Acm aleppo cpc training introduction 1
Acm aleppo cpc training introduction 1Acm aleppo cpc training introduction 1
Acm aleppo cpc training introduction 1
 
FUNDAMENTALS OF PYTHON LANGUAGE
 FUNDAMENTALS OF PYTHON LANGUAGE  FUNDAMENTALS OF PYTHON LANGUAGE
FUNDAMENTALS OF PYTHON LANGUAGE
 
Python-01| Fundamentals
Python-01| FundamentalsPython-01| Fundamentals
Python-01| Fundamentals
 
Introduction to Python - Part Two
Introduction to Python - Part TwoIntroduction to Python - Part Two
Introduction to Python - Part Two
 
PPT on Data Science Using Python
PPT on Data Science Using PythonPPT on Data Science Using Python
PPT on Data Science Using Python
 
Python basics
Python basicsPython basics
Python basics
 
Python in 30 minutes!
Python in 30 minutes!Python in 30 minutes!
Python in 30 minutes!
 
Introduction To Programming with Python
Introduction To Programming with PythonIntroduction To Programming with Python
Introduction To Programming with Python
 
Python made easy
Python made easy Python made easy
Python made easy
 
Python revision tour II
Python revision tour IIPython revision tour II
Python revision tour II
 
Introduction to Python Part-1
Introduction to Python Part-1Introduction to Python Part-1
Introduction to Python Part-1
 
Python cheat-sheet
Python cheat-sheetPython cheat-sheet
Python cheat-sheet
 
Python 3 Programming Language
Python 3 Programming LanguagePython 3 Programming Language
Python 3 Programming Language
 
Programming with Python
Programming with PythonProgramming with Python
Programming with Python
 
Python revision tour i
Python revision tour iPython revision tour i
Python revision tour i
 
Introduction to python programming
Introduction to python programmingIntroduction to python programming
Introduction to python programming
 

Similar a Build Your Own Monads

A Gentle Introduction to Coding ... with Python
A Gentle Introduction to Coding ... with PythonA Gentle Introduction to Coding ... with Python
A Gentle Introduction to Coding ... with PythonTariq Rashid
 
Lec2_cont.pptx galgotias University questions
Lec2_cont.pptx galgotias University questionsLec2_cont.pptx galgotias University questions
Lec2_cont.pptx galgotias University questionsYashJain47002
 
Data oriented design and c++
Data oriented design and c++Data oriented design and c++
Data oriented design and c++Mike Acton
 
BreizhCamp 2013 - Pimp my backend
BreizhCamp 2013 - Pimp my backendBreizhCamp 2013 - Pimp my backend
BreizhCamp 2013 - Pimp my backendHoracio Gonzalez
 
Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987乐群 陈
 
Applying Blackboard Systems to First Person Shooters
Applying Blackboard Systems to First Person ShootersApplying Blackboard Systems to First Person Shooters
Applying Blackboard Systems to First Person Shootershbbalfred
 
JDK8 Functional API
JDK8 Functional APIJDK8 Functional API
JDK8 Functional APIJustin Lin
 
Basic terminologies & asymptotic notations
Basic terminologies & asymptotic notationsBasic terminologies & asymptotic notations
Basic terminologies & asymptotic notationsRajendran
 
02 functions, variables, basic input and output of c++
02   functions, variables, basic input and output of c++02   functions, variables, basic input and output of c++
02 functions, variables, basic input and output of c++Manzoor ALam
 
Basic concept of Python.pptx includes design tool, identifier, variables.
Basic concept of Python.pptx includes design tool, identifier, variables.Basic concept of Python.pptx includes design tool, identifier, variables.
Basic concept of Python.pptx includes design tool, identifier, variables.supriyasarkar38
 
lec_4_data_structures_and_algorithm_analysis.ppt
lec_4_data_structures_and_algorithm_analysis.pptlec_4_data_structures_and_algorithm_analysis.ppt
lec_4_data_structures_and_algorithm_analysis.pptSourabhPal46
 
lec_4_data_structures_and_algorithm_analysis.ppt
lec_4_data_structures_and_algorithm_analysis.pptlec_4_data_structures_and_algorithm_analysis.ppt
lec_4_data_structures_and_algorithm_analysis.pptMard Geer
 
A closure ekon16
A closure ekon16A closure ekon16
A closure ekon16Max Kleiner
 
Python-for-Data-Analysis.pptx
Python-for-Data-Analysis.pptxPython-for-Data-Analysis.pptx
Python-for-Data-Analysis.pptxSandeep Singh
 
Python for Data Analysis.pdf
Python for Data Analysis.pdfPython for Data Analysis.pdf
Python for Data Analysis.pdfJulioRecaldeLara1
 
Python-for-Data-Analysis.pptx
Python-for-Data-Analysis.pptxPython-for-Data-Analysis.pptx
Python-for-Data-Analysis.pptxtangadhurai
 

Similar a Build Your Own Monads (20)

A Gentle Introduction to Coding ... with Python
A Gentle Introduction to Coding ... with PythonA Gentle Introduction to Coding ... with Python
A Gentle Introduction to Coding ... with Python
 
Lec2_cont.pptx galgotias University questions
Lec2_cont.pptx galgotias University questionsLec2_cont.pptx galgotias University questions
Lec2_cont.pptx galgotias University questions
 
Data oriented design and c++
Data oriented design and c++Data oriented design and c++
Data oriented design and c++
 
BreizhCamp 2013 - Pimp my backend
BreizhCamp 2013 - Pimp my backendBreizhCamp 2013 - Pimp my backend
BreizhCamp 2013 - Pimp my backend
 
Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987
 
Applying Blackboard Systems to First Person Shooters
Applying Blackboard Systems to First Person ShootersApplying Blackboard Systems to First Person Shooters
Applying Blackboard Systems to First Person Shooters
 
JDK8 Functional API
JDK8 Functional APIJDK8 Functional API
JDK8 Functional API
 
Python for data analysis
Python for data analysisPython for data analysis
Python for data analysis
 
04 pig data operations
04 pig data operations04 pig data operations
04 pig data operations
 
Interm codegen
Interm codegenInterm codegen
Interm codegen
 
Basic terminologies & asymptotic notations
Basic terminologies & asymptotic notationsBasic terminologies & asymptotic notations
Basic terminologies & asymptotic notations
 
02 functions, variables, basic input and output of c++
02   functions, variables, basic input and output of c++02   functions, variables, basic input and output of c++
02 functions, variables, basic input and output of c++
 
Input Statement.ppt
Input Statement.pptInput Statement.ppt
Input Statement.ppt
 
Basic concept of Python.pptx includes design tool, identifier, variables.
Basic concept of Python.pptx includes design tool, identifier, variables.Basic concept of Python.pptx includes design tool, identifier, variables.
Basic concept of Python.pptx includes design tool, identifier, variables.
 
lec_4_data_structures_and_algorithm_analysis.ppt
lec_4_data_structures_and_algorithm_analysis.pptlec_4_data_structures_and_algorithm_analysis.ppt
lec_4_data_structures_and_algorithm_analysis.ppt
 
lec_4_data_structures_and_algorithm_analysis.ppt
lec_4_data_structures_and_algorithm_analysis.pptlec_4_data_structures_and_algorithm_analysis.ppt
lec_4_data_structures_and_algorithm_analysis.ppt
 
A closure ekon16
A closure ekon16A closure ekon16
A closure ekon16
 
Python-for-Data-Analysis.pptx
Python-for-Data-Analysis.pptxPython-for-Data-Analysis.pptx
Python-for-Data-Analysis.pptx
 
Python for Data Analysis.pdf
Python for Data Analysis.pdfPython for Data Analysis.pdf
Python for Data Analysis.pdf
 
Python-for-Data-Analysis.pptx
Python-for-Data-Analysis.pptxPython-for-Data-Analysis.pptx
Python-for-Data-Analysis.pptx
 

Último

Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...software pro Development
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 

Último (20)

Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 

Build Your Own Monads

  • 1. Build Your Own Monads LambdaWorld 2018, Cadiz Alejandro Serrano Mena 0
  • 3. What are we going to do here? • Understand why custom monads are useful • Learn the different elements in a custom monad • Practice how to create them in various styles • Final tagless / MTL style • Initial style / Free monads 1
  • 4. What are we going to do here? • Understand why custom monads are useful • Learn the different elements in a custom monad • Practice how to create them in various styles • Final tagless / MTL style • Initial style / Free monads Talk! Think! Code! 1
  • 5. Who am I? Alejandro / @trupill in Twitter / @serras in GitHub • Associate Professor at Utrecht University, NL • Teacher of FP courses at various levels • Researcher on FP topics, mostly Haskell • Writer of books about Haskell • Beginning Haskell, published by Apress • The Book of Monads, to appear soon • Advocate of strong typing in programming languages • Haskell, Agda, Idris, LiquidHaskell, … • Secretly in love with Lisp and macros 2
  • 6. Talk! Think! Code! As part of the workshop, we discuss some exercises • Work together with your neighbour! • 5-7 minutes work + 5-7 minutes discussion Some (but not all) exercises involve coding • Haskell? Scala? Whitespace? I don’t care! • Your language must support higher-kinded abstraction Prerequisite: some experience with monads 3
  • 8. The path to monads 1. Discover the most common monads • State, Maybe, Reader, Writer… 2. Learn operations shared among them • mapM, sequence, … 3. Work hard when you require several of them • Usually using monad transformers 4
  • 9. Benefits • Common operations • Once again, mapM, sequence, … • Functor, Applicative, Traversable • Compiler support • do notation, for comprehensions • Well-known set of primitive blocks 5
  • 10. The truth These monads take you a long way 6
  • 11. The truth These monads take you a long way Why bother then? 6
  • 12. The truth These monads take you a long way Why bother then? Abstraction and Safety 6
  • 13. Abstraction Capture your domain better FP provides powerful tools to capture data and their invariants • Algebraic data types and pattern matching • Strong type systems • Contracts for dynamically-typed languages What about processes / services? 7
  • 14. Abstraction Capture your domain better FP provides powerful tools to capture data and their invariants • Algebraic data types and pattern matching • Strong type systems • Contracts for dynamically-typed languages What about processes / services? Custom monads! 7
  • 15. My domain: Tic-Tac-Toe • Query the state of the board data Position = Position ... data Player = O | X deriving (Eq, Ord) info :: Position -> TicTacToe (Maybe Player) • Indicate that we want to claim an empty position • Know whether we have already won or lost data Result = AlreadyTaken { by :: Player } | NextTurn | GameEnded { winner :: Player } take :: Position -> TicTacToe Result 8
  • 16. Safety Ensure that only a subset of operations of a big monad is available in a certain computation • Usually, the big monad is IO Some examples: • Talk only to the database • Restrict console output to logging 9
  • 19. Time to think #1 Talk to each other and find: • Example of a domain to model • Processes or services in that domain • Not too complicated, few primitives 11
  • 21. Syntax and Semantics In our custom monads we usually separate: • The description of computations • Including the available primitives • From the execution of the computations In State, Maybe, … those are intertwined 12
  • 22. Syntax / Algebra 1. Primitive operations for your monad 2. Combinators to describe computations • In addition to the monadic ones In summary, how to describe behaviors in your domain 13
  • 23. Syntax / Algebra 1. Primitive operations for your monad 2. Combinators to describe computations • In addition to the monadic ones In summary, how to describe behaviors in your domain “API” for your monad info :: Position -> TicTacToe (Maybe Player) take :: Position -> TicTacToe Result 13
  • 24. Semantics / Interpretations / Handlers Execute the computations describes by the syntax • Usually mapping each primitive to an action 14
  • 25. Semantics / Interpretations / Handlers Execute the computations describes by the syntax • Usually mapping each primitive to an action More than one interpretation is possible For example, for our TicTacToe monad • Run with console IO • Run on a graphical UI over a network • Mock execution for tests 14
  • 26. Time to think #2 Consider the domain from the first exercise and: • Make the syntax more concrete • Give an API for your primitives • Think of a derived operation using those primitives • Describe one or more interpretations 15
  • 28. Three different styles • Final style / Object algebras / MTL style • Initial style • Pattern abstracted into free monads • Operational style • Pattern abstracted into freer monads 16
  • 29. Three different styles • Final style / Object algebras / MTL style • Initial style • Pattern abstracted into free monads • Operational style • Pattern abstracted into freer monads Initial and operational are fairly similar 16
  • 30. Three different styles For each of the style we need to say how to: 1. Define the syntax of the monad 2. Give a nicer syntax for the API, if required 3. Write computations and which type they get 4. Define interpretations 17
  • 31. Quick summary Final style = Type classes Initial style = Data type with continuations 18
  • 33. Final style: syntax Use a type class or a trait • Each primitive operation is a method in the class • Positions where the monad would appear are replaced by the variable heading the class class TicTacToe m where info :: Position -> m (Maybe Player) take :: Position -> m Result trait TicTacToe[F[_]] { def info(p: Position): F[Option[Player]] def take(p: Position): F[Result] } 19
  • 34. Final style: computations Simply use the monad combinators and the primitives takeIfNotTaken p = do i <- info p case i of Just _ -> return Nothing Nothing -> Just <$> take p 20
  • 35. Final style: computations Simply use the monad combinators and the primitives takeIfNotTaken p = do i <- info p case i of Just _ -> return Nothing Nothing -> Just <$> take p The type reflects that you need a monad which supports the TicTacToe operations takeIfNotTaken :: (Monad m, TicTacToe m) => Position -> m (Maybe Result) 20
  • 36. Why keep Monad separate from TicTacToe? Another possibility, closer to the mtl library: class Monad m => TicTacToe m where info :: Position -> m (Maybe Player) take :: Position -> m Result 21
  • 37. Why keep Monad separate from TicTacToe? Another possibility, closer to the mtl library: class Monad m => TicTacToe m where info :: Position -> m (Maybe Player) take :: Position -> m Result As a result, computations get a “cleaner” type: takeIfNotTaken :: TicTacToe m -- No Monad m => Position -> m (Maybe Result) 21
  • 38. Why keep Monad separate from TicTacToe? Another possibility, closer to the mtl library: class Monad m => TicTacToe m where info :: Position -> m (Maybe Player) take :: Position -> m Result As a result, computations get a “cleaner” type: takeIfNotTaken :: TicTacToe m -- No Monad m => Position -> m (Maybe Result) Personally, I prefer to keep them separate: • Sometimes Applicative is enough • But with this approach Monad infects everything 21
  • 39. Final style: interpretations Each interpretation is an instance of the type class type Board = Map Position Player type RPSBI = ReaderT Player (StateT Board IO) instance TicTacToe RPSBI where info p = lookup p <$> get take p = do l <- info p case l of Just p' -> return AlreadyTaken { by = p' } Nothing -> do me <- ask modify (insert p me) liftIO (putStrLn "Your next move:") ... 22
  • 40. Final style: interpretations For “safety” monads we map into the larger monad class Logging m where log :: String -> m () instance Logging IO where log = putStrLn 23
  • 41. Final style: interpretations For “safety” monads we map into the larger monad class Logging m where log :: String -> m () instance Logging IO where log = putStrLn Q: what is the implementation of…? run :: (forall m. Logging m => m a) -> IO a 23
  • 42. Final style: interpretations For “safety” monads we map into the larger monad class Logging m where log :: String -> m () instance Logging IO where log = putStrLn Q: what is the implementation of…? run :: (forall m. Logging m => m a) -> IO a run x = x 23
  • 43. Time to code #3 Implement your monad in final style: • Define the type class or trait • Implement the derived operation from #2 • Sketch an interpretation 24
  • 45. Initial style: syntax Use a data type with continuations • For each primitive operation op :: A -> B -> ... -> M Z • Create a new constructor in the data type • Add fields of types A, B, … • The last argument is a function Z -> M a which refers back to the monad (that is, a continuation) • Also, we have a constructor with a single field a • Represents the return of the monad 25
  • 46. Initial style: example The primitive operations of our TicTacToe monad: info :: Position -> TicTacToe (Maybe Player) take :: Position -> TicTacToe Result 26
  • 47. Initial style: example The primitive operations of our TicTacToe monad: info :: Position -> TicTacToe (Maybe Player) take :: Position -> TicTacToe Result The TicTacToe data type is defined as: data TicTacToe a = Info Position (Maybe Player -> TicTacToe a) | Take Position (Result -> TicTacToe a) | Done a In Scala the code would be slightly longer… 26
  • 48. Is this thing even a Monad? Let’s build it step by step using GHC holes… 27
  • 49. Is this thing even a Monad? This is the final result: instance Monad TicTacToe where return = Done (Done x) >>= f = f x (Info p k) >>= f = Info p (pl -> k pl >>= f) (Take p k) >>= f = Take p (r -> k r >>= f) 28
  • 50. Reminder of a computation in final style takeIfNotTaken p = do i <- info p case i of Just _ -> return Nothing Nothing -> Just <$> take p How would this look in initial style? 29
  • 51. Initial style: computations takeIfNotTaken p = do i <- info p case i of Just _ -> return Nothing Nothing -> Just <$> take p We have to deal with continuations ourselves • Without any help of do notation takeIfNotTaken p = Info p $ i -> case i of Just _ -> Done Nothing Nothing -> Take p $ r -> Done (Just r) 30
  • 52. Initial style: smart constructors This is a trick to get versions of the primitive operations which we can combine using do notation 31
  • 53. Initial style: smart constructors This is a trick to get versions of the primitive operations which we can combine using do notation This is what we have: Info :: Position -> (Maybe Player -> TicTacToe a) -> TicTacToe a and this is what we want as our API: info :: Position -> TicTacToe (Maybe Player) 31
  • 54. Initial style: smart constructors This is a trick to get versions of the primitive operations which we can combine using do notation This is what we have: Info :: Position -> (Maybe Player -> TicTacToe a) -> TicTacToe a and this is what we want as our API: info :: Position -> TicTacToe (Maybe Player) info p = Info p return -- return :: Maybe Player -> TicTacToe (Maybe Player) 31
  • 55. Initial style: interpretations Interpretations are usually (but not always) natural transformations from our custom monad to another monad runGame :: TicTacToe a -> RPSBI a def runGame :: TicTacToe ~> RPSBI 32
  • 56. Initial style: interpretations Interpretations are usually (but not always) natural transformations from our custom monad to another monad runGame :: TicTacToe a -> RPSBI a def runGame :: TicTacToe ~> RPSBI runGame (Done x) = return x runGame (Info p k) = do pl <- lookup p <$> get runGame (k pl) runGame (Take p k) = do pl <- lookup p <$> get case pl of Just p' -> runGame (k $ AlreadyTaken p') Nothing -> ... 32
  • 57. Continuations in interpretations Note the similarities between the two operations: runGame (Info p k) = do ... runGame (k pl) runGame (Take p k) = do ... runGame (k $ AlreadyTaken p') Always the last line on each branch: • Calls the continuations with some data • Recursively calls runGame 33
  • 58. Time to code #4 Implement your monad in initial style: • Define the corresponding data type and its Monad instance • Implement the derived operation from #2 using continuations manually • Write the smart constructor for each primitive and implement the derived operation again 34
  • 60. All initial style monads are created equal • The data type always has a constructor for return • The other constructors follow a similar shape • Smart constructors are obtained by using return as the continuation • Interpretations into other monads have the same recursive structure 35
  • 61. All initial style monads are created equal • The data type always has a constructor for return • The other constructors follow a similar shape • Smart constructors are obtained by using return as the continuation • Interpretations into other monads have the same recursive structure How to abstract these commonalities? Free monads! 35
  • 62. Free monads: warning My notion of free monads abstract over initial style • Implemented in Haskell’s free package • Corresponds to the categorical notion of free monad of a functor Scalaz and Cats Free abstract over operational style • In Haskell this is known as the freer monad and can be found in the operational package • Very similar, and easier to use 36
  • 63. Separate the common from the specific data TicTacToe a = Info Position (Maybe Player -> TicTacToe a) | Take Position (Result -> TicTacToe a) | Done a -- Specific to TicTacToe data TicTacToeF r = Info Position (Maybe Player -> r) | Take Position (Result -> r) -- Common to all initial style monads data Free f a = Free (f (Free f a)) | Pure a -- All together now type TicTacToe = Free TicTacToeF 37
  • 64. Free monad of a functor Let us have a peek into the Monad instance of Free instance Functor f => Monad (Free f) where return = Pure Pure x >>= f = f x Free x >>= f = Free (fmap (>>= f) x) So we need TicTacToeF to be a functor! 38
  • 65. Free monad of a functor Let us have a peek into the Monad instance of Free instance Functor f => Monad (Free f) where return = Pure Pure x >>= f = f x Free x >>= f = Free (fmap (>>= f) x) So we need TicTacToeF to be a functor! • These data types are always functors • GHC can derive the Functor instance for us data TicTacToeF r = ... deriving Functor 38
  • 66. Smart constructors for free monads Now what we have is slightly different: Info :: Position -> (Maybe Player -> r) -> TicTacToeF r And also what we want to achieve: info :: Position -> Free TicTacToeF (Maybe Player) 39
  • 67. Smart constructors for free monads Now what we have is slightly different: Info :: Position -> (Maybe Player -> r) -> TicTacToeF r And also what we want to achieve: info :: Position -> Free TicTacToeF (Maybe Player) info p = Free _ -- _ has type -- TicTacToeF (Free TicTacToeF (Maybe Player)) 39
  • 68. Smart constructors for free monads Now what we have is slightly different: Info :: Position -> (Maybe Player -> r) -> TicTacToeF r And also what we want to achieve: info :: Position -> Free TicTacToeF (Maybe Player) info p = Free (Info p _) -- _ has type -- (Maybe Player -> Free TicTacToeF (Maybe Player)) 40
  • 69. Smart constructors for free monads Now what we have is slightly different: Info :: Position -> (Maybe Player -> r) -> TicTacToeF r And also what we want to achieve: info :: Position -> Free TicTacToeF (Maybe Player) info p = Free (Info p return) -- Almost as before! -- :) 41
  • 70. Interpretations for free monads We only need to provide the specifics of each operation: runGame' :: TicTacToeF a -> RPSBI a runGame' (Info p k) = do pl <- lookup p <$> get return (k pl) runGame' (Take p k) = ... 42
  • 71. Interpretations for free monads We only need to provide the specifics of each operation: runGame' :: TicTacToeF a -> RPSBI a runGame' (Info p k) = do pl <- lookup p <$> get return (k pl) runGame' (Take p k) = ... The recursive part is tied using foldFree: foldFree :: Monad m => (forall r. f r -> m r) -> Free f a -> m a foldFree _ (Pure x) = return x foldFree f (Free x) = f x >>= foldFree f runGame = foldFree runGame' 42
  • 72. Time to code #5 Rewrite your initial style monad as a free monad • Define the functor for your primitives • Rewrite the smart constructors • Enjoy the reduction in lines! 43
  • 74. Combining several monads Final style monads are very easy to combine fileAndNetwork :: (Monad m, FS m, Network m) => URL -> FilePath -> m Result 44
  • 75. Combining several monads Final style monads are very easy to combine fileAndNetwork :: (Monad m, FS m, Network m) => URL -> FilePath -> m Result Initial style monads are impossible to combine • But we can combine them if they are free monads fileAndNetwork :: URL -> FilePath -> Free (FSF :+: NetworkF) Result 44
  • 76. Combining functors The technique used to combine the operations from two functors is called Data types à la carte data (f :+: g) a = InL (f a) | InR (g a) Although getting good syntax is more complicated 45
  • 77. Performance Peformance of free monads degrades with left-nested binds • Akin to the problem of left-nested concatenation in lists 46
  • 78. Performance Peformance of free monads degrades with left-nested binds • Akin to the problem of left-nested concatenation in lists Several solutions have been proposed: • Church and Scott encodings • Codensity transformation • Type-aligned sequences / “Reflection without Remorse” But there is no clear winner for all cases 46
  • 79. Summary • Custom monads help us modelling behaviors in our domain • There are several styles to build them • Final: using type classes • Initial: using data types • Free monads abstract the commonalities • Operational: not treated today 47
  • 80. Thank you! Feel free to ask me anything during the rest of LambdaWorld 48
  • 81. Thank you! Feel free to ask me anything during the rest of LambdaWorld Let’s go for lunch! 48
  • 83. Why “MTL style”? MTL = Monad Transformer Library • Supports working with monad stacks polymorphically • Defines classes MonadState, MonadReader, and so on • Programmers may mix primitives from several monads in one computation increaseAndLog :: (MonadState Int m, MonadWriter String m) => Int -> m Int increaseAndLog n = do s <- get let new = s + n put new tell $ "New value: " ++ show new ++ "n" 49
  • 84. Smart constructors, generically The free package provides another combinator: liftF :: Functor f => f a -> Free f a liftF = Free . fmap return Using liftF you can write instead: info p = liftF (Info p id) 50