advanced functional programming tim sheard 1 lecture 6 advanced functional programming tim sheard...

34
Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture 7: Monad Transformers •Monads as a data structure •Transformers as functions •Visualizing Transforms (using MetaML) •Transformers as classes

Upload: anna-small

Post on 19-Jan-2018

226 views

Category:

Documents


0 download

DESCRIPTION

Advanced Functional Programming Tim Sheard 3 Lecture 6 Recall definition of monad data Mon m = Mon (forall a. a -> m a) (forall a b. m a -> (a -> m b) -> m b) Monad is a type constructor that takes another type constructor as an argument Mon : * -> * Each component of the pair which is the argument to Mon is a polymorphic function. (forall a. a -> m a)

TRANSCRIPT

Page 1: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 1Lecture 6

Advanced Functional Programming

Tim Sheard Oregon Graduate Institute of Science & Technology

Lecture 7: Monad Transformers•Monads as a data structure•Transformers as functions•Visualizing Transforms (using MetaML)•Transformers as classes

Page 2: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 2Lecture 6

Monad Transfor

mers

A Monad is an ADTAn ADT is a collection of related (typed)

functions that interface some data.A Monad Transformer is a function from

one monad ADT to another.

In order to type a monad transformer we need 2 extensions to Haskell’s type systemHigher order type constructorsRank2 (local) polymorphism

Page 3: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 3Lecture 6

Recall

definition of monad

data Mon m = Mon (forall a . a -> m a) (forall a b . m a -> (a -> m b) -> m b)

Monad is a type constructor that takes another type constructor as an argumentMon : * -> *

Each component of the pair which is the argument to Mon is a polymorphic function.(forall a . a -> m a)

Page 4: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 4Lecture 6

Transfor

mers

type Transformer s t = Mon s -> Mon t

transform :: Mon S -> Mon T

The type T probably mentions S

Page 5: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 5Lecture 6

Three monad

s

--Iddata Id x = Id x

--Envdata Env e x = Env (e -> x)

--Statedata State s x = State (s -> (x,s))

Page 6: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 6Lecture 6

Id monad

data Id x = Id x

idMon :: Mon IdidMon = let bind x f = case x of {(Id y) -> f y } bind (Id y) f = f y in Mon Id bind

runId :: Id a -> arunId (Id x) = x

Page 7: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 7Lecture 6

Env monaddata Env e x = Env (e -> x)

envMon :: Mon (Env e)envMon = let unit x = Env(\ _ -> x) bind (Env g) f = Env(\ e -> case f(g e) of Env h -> h e) in Mon unit bind

readEnv = Env(\ e -> e)inEnv e (Env f) = Env(\ e2 -> f e)

Page 8: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 8Lecture 6

State Monaddata State s x = State (s -> (x,s))stateMon :: Mon (State s)stateMon = let unit x = State(\ s -> (x,s)) bind (State g) f = State(\ s -> let (a,s') = g s State h = f a in h s') in Mon unit bind

readSt = State(\ s -> (s,s))writeSt x = State(\ s -> ((),x))

Page 9: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 9Lecture 6

Env Transfor

mer

data WithEnv env m a = WithEnv (env -> m a)

• m is the old monad• env is the type of the env being added to m• Also need to lift old computations and the

function rdEnv and inEnv

data Fenv m = Fenv (forall a e . m a -> WithEnv e m a) (forall e . WithEnv e m e) (forall a e . e -> WithEnv e m a -> WithEnv e m a)

Page 10: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 10Lecture 6

The transfor

mer

transEnv :: Mon m -> (Mon (WithEnv e m),Fenv m)transEnv (Mon unitM bindM) = let unitEnv x = WithEnv(\ rho -> unitM x) bindEnv x f = WithEnv(\ rho -> let (WithEnv h) = x in bindM (h rho) (\ a -> let (WithEnv g) = f a in g rho)) lift2 x = WithEnv(\ rho -> x) rdEnv = WithEnv(\ rho -> unitM rho) inEnv rho (WithEnv x) = WithEnv(\ _ -> x rho) in (Mon unitEnv bindEnv,Fenv lift2 rdEnv inEnv)

Page 11: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 11Lecture 6

The State Transfor

merdata WithStore s m a = WithStore (s -> m (a,s))

data Fstore m = Fstore (forall a s . m a -> WithStore s m a) (forall s . (s -> s) -> WithStore s m ()) (forall s . WithStore s m s)

Page 12: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 12Lecture 6

The transfor

mer

transStore :: Mon m -> (Mon (WithStore s m),Fstore m)transStore (Mon unitM bindM) = let unitStore x = WithStore(\sigma -> unitM(x,sigma)) bindStore x f = WithStore(\ sigma0 -> let (WithStore h) = x in bindM (h sigma0) (\ (a,sigma1) -> let (WithStore g) = f a in g sigma1 ) ) lift2 x = WithStore(\ sigma -> bindM x (\ y -> unitM(y,sigma))) update f = WithStore(\ sigma -> unitM((),f sigma)) get = WithStore(\sigma -> unitM(sigma,sigma)) in (Mon unitStore bindStore,Fstore lift2 update get)

Page 13: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 13Lecture 6

An exampl

e

ex1 :: (Mon (WithStore a (WithEnv b Id)) ,Fenv Id ,Fstore (WithEnv c Id))

ex1 = let (mon1,funs1) = transEnv idMon (mon2,funs2) = transStore mon1 in (mon2,funs1,funs2)

The problem is that the functions on the inner monad are not lifted.We can use Haskell

Classes to fix this.

Page 14: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 14Lecture 6

Making transformers “visible” in MetaML

datatype ('M : * -> * ) Monad2 = Mon2 of (['a]. <'a -> 'a 'M>) * (['a,'b]. <'a 'M -> ('a -> 'b 'M) -> 'b 'M>);

val id2 = (Mon2 (<Id>, <fn x => fn f => let val (Id y) = x in f y end>));

Page 15: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 15Lecture 6

Env transformer at

the code

level

fun TransEnv2 (Mon2(unitM,bindM)) =let val unitEnv = <fn x => Tenv(fn rho => ~unitM x)>in Mon2(unitEnv, <fn x => fn f => Tenv(fn rho => let val (Tenv h) = x in ~(force (force bindM <h rho>) <fn a => let val (Tenv g) = f a in g rho end> ) end)>) end;

Page 16: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 16Lecture 6

State transfor

mer at

code

level

fun TransStore2 (Mon2(unitM,bindM)) = Mon2(<fn x => Tstore(fn sigma => ~unitM (x,sigma))>, <fn x => fn f => Tstore(fn sigma0 => let val (Tstore h) = x in ~(force (force bindM <h sigma0>) <fn w => let val (a,sigma1) = w val (Tstore g) = f a in g sigma1 end> ) end)>);

Page 17: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 17Lecture 6

An exampl

e-| fun bindof (Mon2(x,y)) = y;

val bindof = Fn : ['a,'b,'c]. 'c Monad2 -> <'b 'c -> ('b -> 'a 'c ) -> 'a 'c >

val ans = bindof(TransStore2 (TransEnv2 id2));

Page 18: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 18Lecture 6

-| val ans = <(fn a => (fn b => Tstore (fn c => let val Tstore d = a in Tenv (fn e => let val Tenv f = d c val Id g = f e val (i,h) = g val Tstore j = b i val Tenv k = j h in k e end) end)))> : <('3 ,'2 ,('1 ,Id) Tenv) Tstore -> ('3 -> ('4 ,'2 ,('1 ,Id) Tenv) Tstore) -> ('4 ,'2 ,('1 ,Id) Tenv) Tstore>

Page 19: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 19Lecture 6

Using Haskell Classes

This part of the lecture is based upon the Monad library developed (in part) by Iavor Diatchki.

Uses classes instead of data stuctures to encode monads.

Instances then are used to encode monad transformers.

Page 20: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 20Lecture 6

From IxEnvMT.hs

newtype WithEnv e m a = E { unE :: e -> m a }

withEnv :: e -> WithEnv e m a -> m awithEnv e (E f) = f e

mapEnv :: Monad m => (e2 -> e1) -> WithEnv e1 m a -> WithEnv e2 m a

mapEnv f (E m) = E (\e -> m (f e))

Page 21: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 21Lecture 6

From IxEnvMT.hs cont.

instance Monad m => Functor (WithEnv e m) where fmap = liftM

instance Monad m => Monad (WithEnv e m) where return = lift . return E m >>= f = E (\e -> do { x <- m e ; unE (f x) e }) E m >> n = E (\e -> m e >> withEnv e n) fail = lift . fail

Page 22: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 22Lecture 6

IxStateMT.hs

newtype WithState s m a = S { ($$) :: s -> m (a,s) }

withSt :: Monad m => s -> WithState s m a -> m awithSt s = liftM fst . withStS s

withStS :: s -> WithState s m a -> m (a,s)withStS s (S f) = f s

mapState :: Monad m => (t -> s) -> (s -> t) -> WithState s m a -> WithState t m amapState inF outF (S m) = S (liftM outF' . m . inF) where outF' (a,s) = (a, outF s)

Page 23: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 23Lecture 6

IxStateMT.hs continued

instance Monad m => Functor (WithState s m) where fmap = liftM

instance Monad m => Monad (WithState s m) where return x = S (\s -> return (x,s)) S m >>= f = S (\s -> m s >>= \(a,s') -> f a $$ s') fail msg = S (\s -> fail msg)

Page 24: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 24Lecture 6

To lift from one monad to another

Add a new class for monad transformers

class MT t where lift :: (Monad m, Monad (t m)) => m a -> t m a

Page 25: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 25Lecture 6

Add instance for each Transformer

instance MT (WithState s) where lift m = S (\s -> do a <- m; return (a,s))

instance MT (WithEnv e) where lift = E . Const

Each Transformer also supports a class of operations – the HasXX classes

Page 26: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 26Lecture 6

HasEnv

class Monad m => HasEnv m ix e | m ix -> e where

getEnv :: ix -> m e inEnv :: ix -> e -> m a -> m a inModEnv :: ix -> (e -> e) -> m a -> m a

inEnv ix e = inModEnv ix (const e) inModEnv ix f m = do { e <- getEnv ix ; inEnv ix (f e) m }

-- define at least one of: -- * getEnv, inEnv -- * getEnv, inModEnv

Page 27: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 27Lecture 6

HasStateclass Monad m => HasState m ix s | m ix -> s where

updSt :: ix -> (s -> s) -> m s -- returns the old state updSt_ :: ix -> (s -> s) -> m () getSt :: ix -> m s setSt :: ix -> s -> m s -- returns the old state setSt_ :: ix -> s -> m () updSt ix f = do s <- getSt ix; setSt ix (f s) setSt ix = updSt ix . const getSt ix = updSt ix id

updSt_ ix f = do updSt ix f; return () setSt_ ix s = do setSt ix s; return ()

-- define at least one of: -- * updSt -- * getSt, setSt

Page 28: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 28Lecture 6

Example use -- Interpreter

Syntax

type Name = Stringtype Message = Stringdata E = E :+: E | E :-: E | E :*: E | E :/: E | Int Int | Let Name E E | Var Name | Print Message E | ReadRef Name | WriteRef Name E | E :> E

Page 29: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 29Lecture 6

The eval functioneval (e1 :+: e2) = liftM2 (+) (eval e1) (eval e2)

eval (e1 :-: e2) = liftM2 (-) (eval e1) (eval e2)eval (e1 :*: e2) = liftM2 (*) (eval e1) (eval e2)eval (e1 :/: e2) = liftM2 div (eval e1) $ (do x <- eval e2 when (x == 0) (raise "division by 0") return x)eval (Int x) = return xeval (Let x e1 e2) = do v <- eval e1; inModEnv ((x,v):) (eval e2)eval (Var x) = (maybe (raise ("undefined variable: " ++ x))

return) . (lookup x =<< getEnv)eval (Print x e) = do v <- eval e output (x ++ show v) return v

eval (ReadRef x) = maybe (return 0) return . lookup x =<< getSteval (WriteRef x e) = do v <- eval e updSt_ $ \s -> (x,v) : filter ((/= x) . fst) s return 0eval (e1 :> e2) = eval e1 >> eval e2

Page 30: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 30Lecture 6

The Type of Eval

eval :: (HasState a Z [([Char],Int)], HasOutput a Z [Char], HasEnv a Z [([Char],Int)], HasExcept a [Char]) => E -> a Int

Page 31: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 31Lecture 6

What Monad has all these?

type Heap = [(Name,Int)]type Env = [(Name,Int)]

type M = WithState Heap ( WithEnv Env ( WithOutput String ( WithExcept String IO )))

Page 32: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 32Lecture 6

instance Monad m => HasEnv (WithEnv e m) Z e where getEnv _ = E return inModEnv _ = mapEnv

instance HasEnv m ix e => HasEnv (WithEnv e' m) (S ix) e where getEnv (Next ix) = lift (getEnv ix) inModEnv (Next ix) f m = E (\e -> inModEnv ix f (withEnv e

m))

instance HasState m ix s => HasState (WithEnv e m) ix s where updSt ix = lift . updSt ix

instance HasOutput m ix o => HasOutput (WithEnv e m) ix o where outputTree ix = lift . outputTree ix

Page 33: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 33Lecture 6

Run for the monad

Then run for the monad is the code that actually specifies how the pieces are put together!

run :: M a -> IO arun m = do x <- removeExcept $ listOutput $ withEnv [] $

withSt [] m case x of Left err -> error ("error: " ++ err) Right (v,o) -> mapM putStrLn o >> return v

Page 34: Advanced Functional Programming Tim Sheard 1 Lecture 6 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science  Technology Lecture

Advanced Functional Programming

Tim Sheard 34Lecture 6

Advanced Features

Multiple occurences of Env, State, etc.