toward haskell transformers

Download Toward Haskell Transformers

Post on 16-Jul-2015

244 views

Category:

Software

0 download

Embed Size (px)

TRANSCRIPT

  • Toward Monad TransformersAntoine Leblanc - @nicuveo

    Functional Programmers Paris

    2015-04-01

  • Outline

    I Monads!I Our missionI TransformersI Building RestTI Wrapping up

    1 / 34

  • Introduction

    What I Wish I Knew When Learning Haskell

    1. Dont read the monad tutorials.2. No really, dont read the monad tutorials.

    8. Dont write monad-analogy tutorials.

    2 / 34

  • Introduction

    What I Wish I Knew When Learning Haskell

    1. Dont read the monad tutorials.

    2. No really, dont read the monad tutorials.

    8. Dont write monad-analogy tutorials.

    2 / 34

  • Introduction

    What I Wish I Knew When Learning Haskell

    1. Dont read the monad tutorials.2. No really, dont read the monad tutorials.

    8. Dont write monad-analogy tutorials.

    2 / 34

  • Introduction

    What I Wish I Knew When Learning Haskell

    1. Dont read the monad tutorials.2. No really, dont read the monad tutorials.

    8. Dont write monad-analogy tutorials.

    2 / 34

  • Introduction

    What I Wish I Knew When Learning Haskell

    1. Dont read the monad tutorials.2. No really, dont read the monad tutorials.

    8. Dont write monad-analogy tutorials.

    2 / 34

  • Typeclass

    class Monad m wherereturn :: a m a

    (>>=) :: m a (a m b) m b

    3 / 34

  • Typeclass

    class Monad m wherereturn :: a m a

    (>>=) :: m a (a m b) m b

    adit.io3 / 34

  • Typeclass

    class Monad m wherereturn :: a m a

    (>>=) :: m a (a m b) m b

    (>>) :: Monad m m a m b m b(>=>) :: Monad m (a m b)

    (b m c) (a m c)

    3 / 34

  • Monad laws

    Using (>>=)

    return a >>= f f am >>= return m(m >>= f) >>= g m >>= (x f x >>= g)

    4 / 34

  • Monad laws

    Using (>=>)

    return >=> f ff >=> return f(f >=> g) >=> h f >=> (g >=> h)

    4 / 34

  • Do notation

    do { a f ; m } f >>= a mdo { f ; m } f >> m

    do { m } m

    5 / 34

  • Do sugar

    f >>= a g >>= b

    h >>= c return (a, b, c)

    doa fb gc hreturn (a, b, c)

    6 / 34

  • Do sugar

    f >>= a g >>= b

    h >>= c return (a, b, c)

    doa f

    b gc hreturn (a, b, c)

    6 / 34

  • ALL TEH MONADS

    Maybe getUser :: Id Maybe User

    Either a parse :: String Either Error ValueList allNextTurns :: Board [Board]IO httpGet :: Url IO StringReader r runReader :: Reader r a r aWriter w runWriter :: Writer w a (a, w)State s runState :: Reader s a s (a, s)

    7 / 34

  • ALL TEH MONADS

    Maybe getUser :: Id Maybe UserEither a parse :: String Either Error Value

    List allNextTurns :: Board [Board]IO httpGet :: Url IO StringReader r runReader :: Reader r a r aWriter w runWriter :: Writer w a (a, w)State s runState :: Reader s a s (a, s)

    7 / 34

  • ALL TEH MONADS

    Maybe getUser :: Id Maybe UserEither a parse :: String Either Error ValueList allNextTurns :: Board [Board]

    IO httpGet :: Url IO StringReader r runReader :: Reader r a r aWriter w runWriter :: Writer w a (a, w)State s runState :: Reader s a s (a, s)

    7 / 34

  • ALL TEH MONADS

    Maybe getUser :: Id Maybe UserEither a parse :: String Either Error ValueList allNextTurns :: Board [Board]IO httpGet :: Url IO String

    Reader r runReader :: Reader r a r aWriter w runWriter :: Writer w a (a, w)State s runState :: Reader s a s (a, s)

    7 / 34

  • ALL TEH MONADS

    Maybe getUser :: Id Maybe UserEither a parse :: String Either Error ValueList allNextTurns :: Board [Board]IO httpGet :: Url IO StringReader r runReader :: Reader r a r a

    Writer w runWriter :: Writer w a (a, w)State s runState :: Reader s a s (a, s)

    7 / 34

  • ALL TEH MONADS

    Maybe getUser :: Id Maybe UserEither a parse :: String Either Error ValueList allNextTurns :: Board [Board]IO httpGet :: Url IO StringReader r runReader :: Reader r a r aWriter w runWriter :: Writer w a (a, w)

    State s runState :: Reader s a s (a, s)

    7 / 34

  • ALL TEH MONADS

    Maybe getUser :: Id Maybe UserEither a parse :: String Either Error ValueList allNextTurns :: Board [Board]IO httpGet :: Url IO StringReader r runReader :: Reader r a r aWriter w runWriter :: Writer w a (a, w)State s runState :: Reader s a s (a, s)

    7 / 34

  • Reader Monad

    Reader Green :: Reader Yellow ::

    (>>=) :: ( )

    runReader :: ( )8 / 34

  • Reader example

    data Conf = { color :: Color, size :: Int }

    formatter :: String Reader Conf Stringformatter p = do

    c asks colors asks sizereturn (undefined) -- TODO

    format :: Conf String Stringformat c s = runReader (textFormatter s) c

    9 / 34

  • Writer Monad

    Writer Green :: Writer Yellow ::

    (>>=) :: ( )

    runWriter :: ( )10 / 34

  • Writer example

    type Log = [String]type Debug = Writer Log

    value :: Int Debug Intvalue x = Writer (x, ["Value"])

    plus :: Debug Int Debug Int Debug Intplus x y = do

    a xb y

    Writer (a + b, "Plus")11 / 34

  • State MonadState Green :: State Yellow ::

    (>>=) :: ( )

    runState :: ( ) 12 / 34

  • State Example

    data GameInfo = GameInfo {turn :: Int,score :: Int}

    skipTurn :: State GameInfo ()skipTurn = do

    t gets turns gets score

    put $ GameInfo (t + 1) (s `div` 2)

    13 / 34

  • Outline

    I MonadsI Our mission!I TransformersI Building RestTI Wrapping up

    14 / 34

  • REST client

    I AuthenticateI Issue simple commandsI Thats it!

    15 / 34

  • Monadic syntax?

    main = run $ dosetServerUrl "http://server.com/api"setCredentials "guest" "guest"authenticateresult request "server.listMyStuff"print $ format result

    16 / 34

  • Problem

    import Network.HTTP.ConduitsimpleHttp :: String IO ByteString

    17 / 34

  • Problem

    import Network.HTTP.ConduitsimpleHttp :: String IO ByteString

    IO!

    17 / 34

  • Problem

    import Network.HTTP.ConduitsimpleHttp :: String IO ByteString

    wait

    17 / 34

  • Problem

    import Network.HTTP.ConduitsimpleHttp :: MonadIO m

    String m ByteString

    MonadIO?

    17 / 34

  • State in IO

    I MVar?I IORef?

    ...add State and Either monads to IO?

    18 / 34

  • State in IO

    I MVar?I IORef?

    ...add State and Either monads to IO?

    18 / 34

  • Outline

    I MonadsI Our missionI Transformers!I Building RestTI Wrapping up

    19 / 34

  • All the way down

    I Monad generalizationI Extra monad parameterI Monad stacks

    20 / 34

  • Monad MonadT

    data State s a = { ... }get :: State s sput :: s State s ()

    Mister21 / 34

  • Monad MonadT

    data StateT s m a = { ... }get :: MonadState s m m sput :: MonadState s m s m ()

    MisterT21 / 34

  • Lifting

    example :: CustomT IO Intexample = do

    customStuff 1lift $ putStrLn "Turtles!"customStuff 2

    22 / 34

  • Lifting

    example :: CustomT (MaybeT IO) Intexample = do

    customStuff 1lift $ lift $ putStrLn "Turtles!"customStuff 2

    22 / 34

  • Instances

    class Monad m MonadState s m whereget :: m sput :: s m ()

    instance MonadState s m MonadState s (ReaderT r m) whereget = lift getput = lift . put

    23 / 34

  • n 2

    IO MonadIO liftIOStateT MonadState getReaderT MonadReader askWriterT MonadWriter tellErrorT MonadError throwError

    24 / 34

  • Outline

    I MonadsI Our missionI TransformersI Building RestT!I Wrapping up

    25 / 34

  • Handling errors: ErrorTtype ErrorMsg = Stringtype Result m a = m (Either ErrorMsg a)

    type RestT m = ErrorT ErrorMsg m

    ..

    m

    .ErrorT ErrorMsg a

    26 / 34

  • Handling errors: ErrorTtype ErrorMsg = Stringtype Result m a = m (Either ErrorMsg a)

    type RestT m = ErrorT ErrorMsg m

    run :: RestT m a Result m arun = runErrorT

    ..

    m

    .ErrorT ErrorMsg a

    26 / 34

  • Handling errors: ErrorTtype ErrorMsg = Stringtype Result m a = m (Either ErrorMsg a)

    type RestT m = ErrorT ErrorMsg m

    run :: RestT m a Result m arun = runErrorT

    liftRest :: m a RestT m aliftRest = lift

    ..

    m

    .ErrorT ErrorMsg a

    26 / 34

  • Adding session: StateTtype ErrorMsg = Stringtype Token = Stringtype Result m a = m (Either ErrorMsg a)

    type RestT m = StateT Token (ErrorT ErrorMsg m)

    ..

    m

    .ErrorT ErrorMsg

    .StateT Token a

    27 / 34

  • Adding session: StateTtype ErrorMsg = Stringtype Token = Stringtype Result m a = m (Either ErrorMsg a)

    type RestT m = StateT Token (ErrorT ErrorMsg m)

    run :: Token RestT m a Result m arun t x = runErrorT $ evalStateT x t

    ..

    m

    .ErrorT ErrorMsg

    .StateT Token a

    27 / 34

  • Adding session: StateTtype ErrorMsg = Stringtype Token = Stringtype Result m a = m (Either ErrorMsg a)

    type RestT m = StateT Token (ErrorT ErrorMsg m)

    run :: Token RestT m a Result m arun t x = runErrorT $ evalStateT x t

    liftRest :: m a RestT m aliftRest = lift . lift

    ..

    m

    .ErrorT ErrorMsg

    .StateT Token a

    27 / 34

  • Dependency injection: ReaderTtype ErrorMsg = Stringtype