Download Slides

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Advanced Functional Programming
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
Lecture 6
Tim Sheard
1
Advanced Functional Programming
Monad Transformers
A Monad is an ADT
An 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
system
Higher order type constructors
Rank2 (local) polymorphism
Lecture 6
Tim Sheard
2
Advanced Functional Programming
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)
Lecture 6
Tim Sheard
3
Advanced Functional Programming
Transformers
type Transformer s t =
Mon s -> Mon t
transform :: Mon S -> Mon T
The type T probably mentions S
Lecture 6
Tim Sheard
4
Advanced Functional Programming
Three monads
--Id
data Id x = Id x
--Env
data Env e x = Env (e -> x)
--State
data State s x = State (s -> (x,s))
Lecture 6
Tim Sheard
5
Advanced Functional Programming
Id monad
data Id x = Id x
idMon :: Mon Id
idMon =
let bind x f = case x of {(Id y) -> f y }
bind (Id y) f = f y
in Mon Id bind
runId :: Id a -> a
runId (Id x) = x
Lecture 6
Tim Sheard
6
Advanced Functional Programming
Env monad
data 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)
Lecture 6
Tim Sheard
7
Advanced Functional Programming
State Monad
data 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))
Lecture 6
Tim Sheard
8
Advanced Functional Programming
Env Transformer
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)
Lecture 6
Tim Sheard
9
Advanced Functional Programming
The transformer
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)
Lecture 6
Tim Sheard
10
Advanced Functional Programming
The State Transformer
data 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)
Lecture 6
Tim Sheard
11
Advanced Functional Programming
The transformer
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)
Lecture 6
Tim Sheard
12
Advanced Functional Programming
An example
The problem is that the
functions on the inner
monad are not lifted.
We can use Haskell Classes to
fix this.
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)
Lecture 6
Tim Sheard
13
Advanced Functional Programming
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>));
Lecture 6
Tim Sheard
14
Advanced Functional Programming
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;
Lecture 6
Tim Sheard
15
Advanced Functional Programming
State transformer 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)>);
Lecture 6
Tim Sheard
16
Advanced Functional Programming
An example
-| 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));
Lecture 6
Tim Sheard
17
Advanced Functional Programming
-| 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>
Lecture 6
Tim Sheard
18
Advanced Functional Programming
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.
Lecture 6
Tim Sheard
19
Advanced Functional Programming
From IxEnvMT.hs
newtype WithEnv e m a =
E { unE :: e -> m a }
withEnv :: e -> WithEnv e m a -> m a
withEnv 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))
Lecture 6
Tim Sheard
20
Advanced Functional Programming
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
Lecture 6
Tim Sheard
21
Advanced Functional Programming
IxStateMT.hs
newtype WithState s m a =
S { ($$) :: s -> m (a,s) }
withSt :: Monad m => s -> WithState s m a -> m a
withSt 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 a
mapState inF outF (S m) = S (liftM outF' . m . inF)
where outF' (a,s) = (a, outF s)
Lecture 6
Tim Sheard
22
Advanced Functional Programming
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)
Lecture 6
Tim Sheard
23
Advanced Functional Programming
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
Lecture 6
Tim Sheard
24
Advanced Functional Programming
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
Lecture 6
Tim Sheard
25
Advanced Functional Programming
HasEnv
class Monad
where
getEnv
inEnv
inModEnv
m => HasEnv m ix e | m ix -> e
:: ix -> m e
:: ix -> e -> m a -> m a
:: ix -> (e -> e) -> m a -> m a
inEnv ix e
inModEnv ix f m
= inModEnv ix (const e)
= do { e <- getEnv ix
; inEnv ix (f e) m }
-- define at least one of:
-- * getEnv, inEnv
-- * getEnv, inModEnv
Lecture 6
Tim Sheard
26
Advanced Functional Programming
HasState
class 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
setSt ix
getSt ix
= do s <- getSt ix; setSt ix (f s)
= updSt ix . const
= 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
Lecture 6
Tim Sheard
27
Advanced Functional Programming
Example use -- Interpreter
Syntax
type Name
type Message
data E
Lecture 6
= String
= String
= 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
Tim Sheard
28
Advanced Functional Programming
The eval function
eval
eval
eval
eval
(e1
(e1
(e1
(e1
:+:
:-:
:*:
:/:
e2)
e2)
e2)
e2)
eval (Int x)
eval (Let x e1 e2)
eval (Var x)
return) .
eval (Print x e)
eval (ReadRef x)
eval (WriteRef x e)
eval (e1 :> e2)
Lecture 6
=
=
=
=
liftM2 (+) (eval e1) (eval e2)
liftM2 (-) (eval e1) (eval e2)
liftM2 (*) (eval e1) (eval e2)
liftM2 div (eval e1) $
(do x <- eval e2
when (x == 0) (raise "division by 0")
return x)
= return x
= do v <- eval e1; inModEnv ((x,v):) (eval e2)
= (maybe (raise ("undefined variable: " ++ x))
(lookup x =<< getEnv)
= do v <- eval e
output (x ++ show v)
return v
= maybe (return 0) return . lookup x =<< getSt
= do v <- eval e
updSt_ $ \s -> (x,v) : filter ((/= x) . fst) s
return 0
= eval e1 >> eval e2
Tim Sheard
29
Advanced Functional Programming
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
Lecture 6
Tim Sheard
30
Advanced Functional Programming
What Monad has all these?
type Heap
type Env
type M
Lecture 6
= [(Name,Int)]
= [(Name,Int)]
= WithState Heap
( WithEnv Env
( WithOutput String
( WithExcept String IO
)))
Tim Sheard
31
Advanced Functional Programming
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
Lecture 6
Tim Sheard
32
Advanced Functional Programming
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 a
run m =
do x <- removeExcept $ listOutput $ withEnv [] $
withSt [] m
case x of
Left err
-> error ("error: " ++ err)
Right (v,o) -> mapM putStrLn o >> return v
Lecture 6
Tim Sheard
33
Advanced Functional Programming
Advanced Features
Multiple occurences of Env, State, etc.
Lecture 6
Tim Sheard
34
Related documents