(2015 06-16) Three Approaches to Monads

92
Three Approaches to Monads Chris Evans June 16, 2015

Transcript of (2015 06-16) Three Approaches to Monads

Page 1: (2015 06-16) Three Approaches to Monads

Three Approaches to MonadsChris Evans

June 16, 2015

Page 2: (2015 06-16) Three Approaches to Monads

Three Approaches

I. How Monads Arise. (Ref: You Could Have Invented Monads)

II. Monads in Haskell (Ref: Real World Haskell)

III.Monads in Category Theory (Ref: Wikibooks - Haskell/Category Theory)

Page 3: (2015 06-16) Three Approaches to Monads

I. How Monads Arise

Page 4: (2015 06-16) Three Approaches to Monads

In a typed language considerf,g : Float -> Float

and their compositiong . f : Float -> Float

Example (A)

Page 5: (2015 06-16) Three Approaches to Monads

What if we want debugging information?f : Float -> (Float, String)f(x) = (2*x, “Doubled!”)

g : Float -> (Float, String)g(x) = (x/4, “Quartered!”)

Page 6: (2015 06-16) Three Approaches to Monads

Now we can’t compose them. Yet there is an obvious “composition”:

x |-> ((2*x)/4, “Doubled! Quartered!”)

Page 7: (2015 06-16) Three Approaches to Monads

Example (B)Consider multi-valued functionsf : Advertisable -> [Campaign]g : Campaign -> [Ad]

We can’t compose them but there is a natural “composition”

Page 8: (2015 06-16) Three Approaches to Monads

(In Python)

adv |-> [g(camp) for camp in f(adv)]

But this gets ugly for multiple compositions...

Page 9: (2015 06-16) Three Approaches to Monads

Example (C)Consider functions with possible failure

f : Logline -> TimeStamp (Not in Logline?)

g : TimeStamp -> DayOfWeek (Parsing fails?)

Page 10: (2015 06-16) Three Approaches to Monads

We can add a Bool to indicate successf : Logline -> (TimeStamp, Bool)g : TimeStamp -> (DayOfWeek, Bool)

We can no longer compose them but there is again a natural “composition” (propagate failure)

Page 11: (2015 06-16) Three Approaches to Monads

These three examples are similar.

Each involves a “decorated type”(A) (Float, String) for Float (B) [Campaign] for Campaign(C) (TimeStamp, Bool) for TimeStamp

Page 12: (2015 06-16) Three Approaches to Monads

For each example, we first define two functions, unit and bind.

unit -- maps basic type to decorated typebind -- “upgrades” function which takes basic

type to instead take decorated type

Page 13: (2015 06-16) Three Approaches to Monads

Example (A)unit : Float -> (Float, String)

bind : (Float -> (Float, String)) -> ((Float, String) -> (Float, String))

Page 14: (2015 06-16) Three Approaches to Monads

Example (A)unit : Float -> (Float, String) x |-> (x, “”)

bind : (Float -> (Float, String)) -> ((Float, String) -> (Float, String))

Page 15: (2015 06-16) Three Approaches to Monads

Example (A)unit : Float -> (Float, String) x |-> (x, “”)

bind : (Float -> (Float, String)) -> ((Float, String) -> (Float, String))

(bind f)(x, old_str) = let (y, new_str) = f x in (y, old_str ++ new_str)

Page 16: (2015 06-16) Three Approaches to Monads

Example (B)unit : Campaign -> [Campaign]

bind : (Campaign -> [Ad]) -> ([Campaign] -> [Ad])

Page 17: (2015 06-16) Three Approaches to Monads

Example (B)unit : Campaign -> [Campaign] camp |-> [camp]

bind : (Campaign -> [Ad]) -> ([Campaign] -> [Ad])

Page 18: (2015 06-16) Three Approaches to Monads

Example (B)unit : Campaign -> [Campaign] camp |-> [camp]

bind : (Campaign -> [Ad]) -> ([Campaign] -> [Ad])

(bind f) campaigns = flatten([f(camp) for camp in campaigns])

Page 19: (2015 06-16) Three Approaches to Monads

Example (C)unit : TimeStamp -> (TimeStamp, Bool)

bind : (TimeStamp -> (DayOfWeek, Bool)) -> ((TimeStamp, Bool) -> (DayOfWeek, Bool))

Page 20: (2015 06-16) Three Approaches to Monads

Example (C)unit : TimeStamp -> (TimeStamp, Bool) ts |-> (ts, True)

bind : (TimeStamp -> (DayOfWeek, Bool)) -> ((TimeStamp, Bool) -> (DayOfWeek, Bool))

Page 21: (2015 06-16) Three Approaches to Monads

Example (C)unit : TimeStamp -> (TimeStamp, Bool) ts |-> (ts, True)

bind : (TimeStamp -> (DayOfWeek, Bool)) -> ((TimeStamp, Bool) -> (DayOfWeek, Bool)) (bind f)(x,b) = case b of True -> f(x) False -> (??, False)

Page 22: (2015 06-16) Three Approaches to Monads

Pointsbind gives us the desired composition! Instead of g.f do (bind g).f

Page 23: (2015 06-16) Three Approaches to Monads

Pointsbind gives us the desired composition! Instead of g.f do (bind g).funit can be used to start the chain. Instead of g.f do (bind g).(bind f).unit

Page 24: (2015 06-16) Three Approaches to Monads

Pointsbind gives us the desired composition! Instead of g.f do (bind g).funit can be used to start the chain. Instead of g.f do (bind g).(bind f).unitunit/bind depend only on the “type extension”. e.g. there is a unit/bind for List not List-of-Strings.

Page 25: (2015 06-16) Three Approaches to Monads

The Big RevealEach example is an example of a monad! But what is a monad?

Page 26: (2015 06-16) Three Approaches to Monads

For Part I we’ll define a monad as “A type extension together with an implementation of unit and bind”

Ex: [](, String)(, Bool)

Page 27: (2015 06-16) Three Approaches to Monads

II. Monads in Haskell

Page 28: (2015 06-16) Three Approaches to Monads

HaskellStrongly/Statically typed (cannot even add Integer and Float!)

Pure functional language (absolutely no side effects. I/O must be handled specially)

There’s a type for that (where other languages use enums/structs/classes, Haskell uses types)

Page 29: (2015 06-16) Three Approaches to Monads

Defining Haskell Types

Page 30: (2015 06-16) Three Approaches to Monads

Type Synonyms: (type)type TimeStamp = Stringtype Advertisable = Stringtype Campaign = String

Syntactic sugar for existing types. In facttype String = [Char]

Page 31: (2015 06-16) Three Approaches to Monads

New Data Types: (data)type Name = Stringtype Age = Intdata Customer = Customer Name Age

“type constructor” “value constructor”

Page 32: (2015 06-16) Three Approaches to Monads

Algebraic Data Types: data Bool = True | Falsedata Color = Red | Blue | Greendata LineType = Impression |Click |Win |Bid

value constructors

Page 33: (2015 06-16) Three Approaches to Monads

More Algebraic Data Types: type CPM = Floattype VCPC = Floattype ClickProb = Floatdata PricingStrategy = FixedBid CPM |BidIQ VCPC

bid_price :: PricingStrategy -> ClickProb -> CPMbid_price strat p = case strat of FixedBid cpm -> cpm BidIQ vcpc -> vcpc * p

Page 34: (2015 06-16) Three Approaches to Monads

Parameterized Types:

data Maybe a = Just a | Nothingdata List a = Cons a (List a) | Nildata Tree a = Node a (Tree a) (Tree a) |Empty

Then can use Maybe String or List Float

Page 35: (2015 06-16) Three Approaches to Monads

Type Classes:

<<WARNING>> NOTHING LIKE CLASSES IN OO LANGUAGES! More like interfaces in OO languages...

Page 36: (2015 06-16) Three Approaches to Monads

Example: The Show Typeclassclass Show a where show :: a -> String

data LineType = Impression | Click | Win

instance Show LineType where show Impression = “imp” show Click = “cli” show Win = “win”

Page 37: (2015 06-16) Three Approaches to Monads

In fact the Haskell REPL uses show to display results!

Page 38: (2015 06-16) Three Approaches to Monads

Example: The Eq Typeclassclass Eq a where (==),(/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y)

Only need to define one, the other comes free!

Page 39: (2015 06-16) Three Approaches to Monads
Page 40: (2015 06-16) Three Approaches to Monads
Page 41: (2015 06-16) Three Approaches to Monads

Enter Monads!

Page 42: (2015 06-16) Three Approaches to Monads

Monads in Haskell are just a typeclass

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

...which a parameterized type can implement!

Page 43: (2015 06-16) Three Approaches to Monads

Revisit the Examples in Part I

Page 44: (2015 06-16) Three Approaches to Monads

Example (B) -- The List Monad

instance Monad [] where return x = [x] xs >>= f = concat (map f xs)

(This is in the Haskell Prelude)

Page 45: (2015 06-16) Three Approaches to Monads
Page 46: (2015 06-16) Three Approaches to Monads
Page 47: (2015 06-16) Three Approaches to Monads
Page 48: (2015 06-16) Three Approaches to Monads

The Control.Monad library provides >=> for direct composition.

Page 49: (2015 06-16) Three Approaches to Monads

Haskell do syntax and list comprehensions

Page 50: (2015 06-16) Three Approaches to Monads

Example (C) -- The Maybe Monad

instance Monad Maybe where return x = Just x (Just x) >>= f = f x Nothing >>= f = Nothing

(This is in the Haskell Prelude)

Page 51: (2015 06-16) Three Approaches to Monads
Page 52: (2015 06-16) Three Approaches to Monads
Page 53: (2015 06-16) Three Approaches to Monads

Example (A) -- The History Monaddata History a = History a String

instance Monad History where return x = History x “” (History x old) >>= f = let (History y new) = f x in History y (old ++ new)

-- Implementation of Show omitted --

(Not in Prelude -- this is our creation)

Page 54: (2015 06-16) Three Approaches to Monads
Page 55: (2015 06-16) Three Approaches to Monads
Page 56: (2015 06-16) Three Approaches to Monads

Bonus Monad -- IO MonadI/O in Haskell is handled via the IO Monad.

e.g. Haskell’s “print” isputStrLn :: String -> IO ()

Page 57: (2015 06-16) Three Approaches to Monads
Page 58: (2015 06-16) Three Approaches to Monads

Part II TakeawaysIn Haskell, a Monad is just a typeclass... which a parametric type can implement by

implementing return and (>>=).Basic I/O in Haskell uses the IO Monad.do syntactic sugar emulates imperative code.

Page 59: (2015 06-16) Three Approaches to Monads

III. Monads in Category Theory

Page 60: (2015 06-16) Three Approaches to Monads

Category TheoryA category is a collection of objectsarrows/morphisms between pairs of objectsnotion of composition of arrowssatisfying(Associativity) h.(g.f) = (h.g).f(Identity) id . f = f , g . id = g

Page 61: (2015 06-16) Three Approaches to Monads

Ex: Set (Category of Sets)

Objects: SetsArrows: Functions between sets

Note: Set contains all sets and all functions between sets in the universe!

Page 62: (2015 06-16) Three Approaches to Monads

Set

{1, 3}

{2, 4}

{7, 8, 1}

id

f

id

g

h

g . f

r

Page 63: (2015 06-16) Three Approaches to Monads

Ex: Hask (Category of Haskell Types)

Objects: Haskell typesArrows: Haskell functions

Note: Hask contains all types and all functions in the universe!

Page 64: (2015 06-16) Three Approaches to Monads

Hask

[String]

String

Integer

id

my_join

id

my_len

my_func

my_split

Page 65: (2015 06-16) Three Approaches to Monads

FunctorsA functor is a mapping F between categories C and D.Maps each object X in C to F(X) in DMaps each arrow f : X -> Y to F(f) : F(X) -> F(Y)satisfyingF(id) = idF(g . f)=F(g) . F(f)

Page 66: (2015 06-16) Three Approaches to Monads

Ex: Powerset Functor P : Set -> SetMaps each set (object) to its power set e.g. P({1,2}) = { ϕ , {1}, {2}, {1,2} }

Maps arrow f : X -> Y to P(f) : P(X) -> P(Y) by [F(f)](S) = { f(s) | s in S}

(exercise: check that functor conditions are satisfied)

Page 67: (2015 06-16) Three Approaches to Monads

MonadsA monad is a functor M : C -> C along with two mappings for every object X in C.unit : X -> M(X)join : M(M(X)) -> M(X)

such that unit and join satisfy certain properties (“monad laws”)...

Page 68: (2015 06-16) Three Approaches to Monads

Monad Laws

1.join . M(join) = join . join2.join . M(unit) = join . unit = id3.unit . f = M(f) . unit4.join . M(M(f)) = M(f) . join

Page 69: (2015 06-16) Three Approaches to Monads

Ex: Powerset Functor is a Monadwhere unit : X -> P(X)

join : P(P(X)) -> P(X)

Page 70: (2015 06-16) Three Approaches to Monads

Ex: Powerset Functor is a Monadwhere unit : X -> P(X) unit(x) = {x}

join : P(P(X)) -> P(X)

Page 71: (2015 06-16) Three Approaches to Monads

Ex: Powerset Functor is a Monadwhere unit : X -> P(X) unit(x) = {x}

join : P(P(X)) -> P(X)

join(S) = U

s in Ss

Page 72: (2015 06-16) Three Approaches to Monads

Check Monad Laws (We’ll just check #3 here)3) unit . f = P(f) . unitConsider f : {1, 2} -> {3, 4, 5} 1 |-> 3, 2 |-> 5

(unit . f)(1) = unit(f(1)) = unit(3) = {3}(P(f).unit)(1) = [P(f)](unit(1)) = [P(f)]({1}) = {3}

same!

Page 73: (2015 06-16) Three Approaches to Monads

Back to Hask[ ] is a functor from Hask to Hask.● Maps objects:

● Maps functions:

Page 74: (2015 06-16) Three Approaches to Monads

Back to Hask[ ] is a functor from Hask to Hask.● Maps objects:

Maps type to list of that type

● Maps functions:

Page 75: (2015 06-16) Three Approaches to Monads

Back to Hask[ ] is a functor from Hask to Hask.● Maps objects:

Maps type to list of that type

● Maps functions: e.g. maps function f : String -> Float to [ ](f): [String] -> [Float] by [ ](f) = map f

Page 76: (2015 06-16) Three Approaches to Monads

In fact, [ ] is a monad from Hask to Hask.

unit : X -> [X]

join : [[X]] -> [X]

Page 77: (2015 06-16) Three Approaches to Monads

In fact, [ ] is a monad from Hask to Hask.

unit : X -> [X] x |-> [x]

join : [[X]] -> [X]

Page 78: (2015 06-16) Three Approaches to Monads

In fact, [ ] is a monad from Hask to Hask.

unit : X -> [X] x |-> [x]

join : [[X]] -> [X] list_of_lists |-> concat list_of_lists

Page 79: (2015 06-16) Three Approaches to Monads

In fact, [ ] is a monad from Hask to Hask.

unit : X -> [X] x |-> [x]

join : [[X]] -> [X] list_of_lists |-> concat list_of_lists

(Exercise: Check the monad laws)

Page 80: (2015 06-16) Three Approaches to Monads

Maybe is a functor from Hask to Hask.● Maps objects:

● Maps functions:

Page 81: (2015 06-16) Three Approaches to Monads

Maybe is a functor from Hask to Hask.● Maps objects:

e.g. maps String to Maybe String

● Maps functions:

Page 82: (2015 06-16) Three Approaches to Monads

Maybe is a functor from Hask to Hask.● Maps objects:

e.g. maps String to Maybe String

● Maps functions: given f : X -> Y define Maybe f : Maybe X -> Maybe Y Just x |-> Just (f x) Nothing |-> Nothing

Page 83: (2015 06-16) Three Approaches to Monads

In fact, Maybe is a monad from Hask to Hask.

unit : X -> Maybe X

join : Maybe (Maybe X) -> Maybe X

Page 84: (2015 06-16) Three Approaches to Monads

In fact, Maybe is a monad from Hask to Hask.

unit : X -> Maybe X x |-> Just x

join : Maybe (Maybe X) -> Maybe X

Page 85: (2015 06-16) Three Approaches to Monads

In fact, Maybe is a monad from Hask to Hask.

unit : X -> Maybe X x |-> Just x

join : Maybe (Maybe X) -> Maybe X Just (Just x) |-> Just x Just Nothing |-> Nothing Nothing |-> Nothing

Page 86: (2015 06-16) Three Approaches to Monads

In fact, Maybe is a monad from Hask to Hask.

unit : X -> Maybe X x |-> Just x

join : Maybe (Maybe X) -> Maybe X Just (Just x) |-> Just x Just Nothing |-> Nothing Nothing |-> Nothing

(Exercise: Check the monad laws)

Page 87: (2015 06-16) Three Approaches to Monads

Wait… definitions seem different?Part II (Haskell):Monad is a typeclassand you defineunit/returnbind/(>>=)

Part III (Categories):Monad is a functorand you definehow it maps functionsunitjoin

and check monad laws!

Page 88: (2015 06-16) Three Approaches to Monads

Answers● Haskell Monad is just a programming construct

○ Doesn’t require monad laws to compile○Typeclass could have a different name

Page 89: (2015 06-16) Three Approaches to Monads

Answers● Haskell Monad is just a programming construct

○ Doesn’t require monad laws to compile○Typeclass could have a different name

● Haskell also has a typeclass Functor○ Implements fmap ○But Monad instance need not be Functor instance

Page 90: (2015 06-16) Three Approaches to Monads

Answers● return, (>>=) are equivalent to unit, join, fmap by unit = return join x = x >>= id fmap f x = x >>=(return.f)

return = unit x >>= f = join(fmap f x)

Page 91: (2015 06-16) Three Approaches to Monads

Fin

Page 92: (2015 06-16) Three Approaches to Monads

BibliographyPiponi, Dan “You Could Have Invented Monads!”

http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html. August, 2006. Accessed June, 2015.

O’Sullivan, B., Stewart, D., Goerzen, J. Real World Haskell. O’Reilly Media, 2008. Print.

https://en.wikibooks.org/wiki/Haskell/Category_theory