Presentation is loading. Please wait.

Presentation is loading. Please wait.

Tim Sheard Oregon Graduate Institute Lecture 6: Monads and Interpreters CSE 510 Section FSC Winter 2004 Winter 2004.

Similar presentations


Presentation on theme: "Tim Sheard Oregon Graduate Institute Lecture 6: Monads and Interpreters CSE 510 Section FSC Winter 2004 Winter 2004."— Presentation transcript:

1 Tim Sheard Oregon Graduate Institute Lecture 6: Monads and Interpreters CSE 510 Section FSC Winter 2004 Winter 2004

2 2Cs510 FSC Winter 2005 Interpreters are hard to modify Consider the interpreters for Exp and Com Consider 3 extensions Adding a print command Adding a divide expression and catching divide by 0 errors Adding a notion of multiple results Drastic changes need to be made to the structure of the interpreter.

3 3Cs510 FSC Winter 2005 Extended Abstract Syntax datatype Exp = Constant of int (* 5 *) | Variable of string (* x *) | Minus of (Exp * Exp) (* x - 5 *) | Greater of (Exp * Exp) (* x > 1 *) | Times of (Exp * Exp) (* x * 4 *) | Divide of (Exp * Exp) (* x / 3 *) datatype Com = Assign of (string * Exp) (* x := 1 *) | Seq of (Com * Com) (* { x := 1; y := 2 } *) | If of (Exp * Com * Com) (* if x then x := 1 else y := 1 *) | While of (Exp * Com) (* while x>0 do x := x - 1 *) | Declare of (string * Exp * Com) (* Declare x = 1 in x := x - 1 *) | Print of string * Exp (* Print "answer" (x+2) *)

4 4Cs510 FSC Winter 2005 Adding a Print command New types type env = (string * int) list eval0 : Exp -> env -> int interp1 : Com -> env -> (env * string) The type of Eval doesn’t change since evaluation of Exp can’t cause any printing. A Com is an env transformer and an output producer. String produced by printing

5 5Cs510 FSC Winter 2005 New interp function fun interp1 stmt env = case stmt of Assign(name,e) => let val v = eval0 e env in (set name v env,"") end | Seq(x1,x2) => let val (env1,s1) = interp1 x1 env val (env2,s2) = interp1 x2 env1 in (env2,s1 ^ s2) end | If(e,s1,s2) => let val x = eval0 e env in if x=1 then interp1 s1 env else interp1 s2 env end Assignment cause no output Collect output from both sub-commands

6 6Cs510 FSC Winter 2005 Interp continued | While(e,body) => let fun loop env s = let val v = eval0 e env in if v=0 then (env,s) else let val (env1,s1) = interp1 body env in loop env1 (s^s1) end end in loop env "" end | Declare(nm,e,stmt) => let val v = eval0 e env val env1 = ext nm v env val (env2,s) = interp1 stmt env1 in (remove env2,s) end; Output collected from many traversals of loop Env is shrunk but output is propagated

7 7Cs510 FSC Winter 2005 Add Divide and error catching New types eval2 : Exp -> env -> int option interp2 : Com -> env -> env option Where Datatype ‘a option = NONE | SOME of ‘a

8 8Cs510 FSC Winter 2005 Eval2 fun eval2 exp env = case exp of Constant n => SOME n | Variable s => SOME (lookup s env) | Minus(x,y) => (case eval2 x env of SOME a => (case eval2 y env of SOME b => SOME(a - b) | _ => NONE) |... (* similar for Greter and Times *) | Divide(x,y) => (case eval2 x env of SOME a => (case eval2 y env of SOME 0 => NONE | SOME b => SOME(a div b) | _ => NONE) Error production Error propagation

9 9Cs510 FSC Winter 2005 interp2 fun interp2 stmt env = case stmt of Assign(name,e) => (case eval2 e env of SOME v => SOME(set name v env) | _ => NONE) | Seq(s1,s2) => (case interp2 s1 env of SOME env1 => interp2 s2 env1 | NONE => NONE) | If(e,s1,s2) => (case eval2 e env of SOME x => if x=1 then interp2 s1 env else interp2 s2 env | NONE => NONE) |... (* similar for While etc. *)

10 10Cs510 FSC Winter 2005 Additions for multiple values E.g. Suppose x  [9,5] y  [2,4] Then (x – y)  [7,5,3,1] [9-2, 9-4, 5-2, 5-4] New types type env = (string * int list) list; eval3 : Exp -> env -> int list Interp3 : Com -> env -> env Useful function – combines map and append fun mapp f [] = [] | mapp f (x::xs) = (f x) @ (mapp f xs); Appends results rather than consing them

11 11Cs510 FSC Winter 2005 Eval3 fun eval3 exp env = case exp of Constant n => [n] | Variable s => lookup s env | Minus(x,y) => let val xs = eval3 x env fun f x = let val ys = eval3 y env fun g y = [x - y] in mapp g ys end in mapp f xs end | Greater(x,y) => let val xs = eval3 x env fun f x = let val ys = eval3 y env fun g y = [ if x '>' y then 1 else 0] in mapp g ys end in mapp f xs end |... Constants have singleton values Recursive calls give multiple results which are then combined

12 12Cs510 FSC Winter 2005 Example run val env3 = [("x",[9,5]),("y",[2,4])] val test2 = eval3 (Minus (Variable "x",Variable "y")) env3; -| test2; val it = [7,5,3,1] : int list

13 13Cs510 FSC Winter 2005 Notes Each new addition made drastic changes to the structure of the code. Print – extra results returned in pair Divide – case analysis to determine if SOME or NONE Mulitiple Answers – results are lists, need complicated use of mapp to combine results Consider making an interpreter with all three changes

14 14Cs510 FSC Winter 2005 Patterns (x,””)SOME x[x] Let val (a,s) = e1 val (b,t) = e2 In f[s^t] Case e of SOME z => m NONE => NONE Let val xs = e fun f x = … In mapp f xs end These patterns can be captured by two functions Return : ‘a -> ‘a M Bind : ‘a M -> (‘a -> ‘b M) -> ‘b M Where M is some type constructor. This pattern is called a Monad ‘a M = (‘a * string) ‘a M = ‘a option ‘a M = ‘a list

15 15Cs510 FSC Winter 2005 Output monad fun return x = (x,""); fun bind (x,s1) g = let val (y,s2) = g x in (y,s1^s2) end;

16 16Cs510 FSC Winter 2005 Error Monad datatype ‘a option = NONE | SOME of fun return x = SOME x; fun bind (SOME x) g = g x | bind NONE g = NONE;

17 17Cs510 FSC Winter 2005 Monad of Multiple results datatype ‘a list = [] | ‘a :: ‘a list; fun return x = [x]; fun bind xs g = mapp g xs;

18 18Cs510 FSC Winter 2005 Monads in Meta ML Monads are built into MetaML Users can define their own Monads Monads support their own special syntax Do m { x y) Return m x === return x Monads require extensions to ML Higher order type constructors  Type constructors (I.e. things like list) which take type constructors as arguments Polymorphic components to records

19 19Cs510 FSC Winter 2005 Higher Order Type Constructors datatype ('a,'T : * -> * ) tree = Tip of 'a | Node of (('a,'T)tree) 'T; datatype 'a binary = bin of 'a * 'a; val z: (int,list) tree = Node [ Tip 4, Tip 2 ]; val w: (int,binary ) tree = Node(bin (Tip 1,Node(bin (Tip 3, Tip 0))));

20 20Cs510 FSC Winter 2005 Polymorphic Components datatype a = A of (['a].'a list -> 'a list); fun copy [] = [] | copy (x::xs) = x :: (copy xs); val a1 = A(rev); val a2 = A copy; -| fun f x y (A g) = (g x, g y); val f = Fn : ['a,'b].'b list -> 'a list -> a -> ('b list * 'a list ) -| val q = f [1,2,3] ["x","y","d"] a1; val q = ([3,2,1],["d","y","x"]) : (int list * string list )

21 21Cs510 FSC Winter 2005 List Monoid example datatype list_monoid = LM of { inject : ['a].'a -> 'a list, plus : ['a]. 'a list -> 'a list -> 'a list, zero : ['a].'a list }; val lm1 = LM{inject = fn x => [x], plus = fn x => fn y => x@y, zero = []}

22 22Cs510 FSC Winter 2005 Pattern Matching to access fun f (LM{inject=inj, plus = sum, zero = z}) = (sum z (inj 2), sum (inj true) (inj false)); -| f lm1; val it = ([2],[true,false ]) : (int list * bool list )

23 23Cs510 FSC Winter 2005 Monads A Monad is A type constructor T  a type to type function and 2 polymorphic functions  unit : ‘a -> ‘a T  bind: (‘a T) -> (‘a -> ‘b T) -> (‘b T) an expression with type ‘a T is a computation returns a value of type ‘a might perform a T action  Print, propogate errors, return multiple results

24 24Cs510 FSC Winter 2005 Instances of Monad Actions Performing input/output Changing the value of a mutable variable Raising an exception Monads can be “emulated” with pure functional programs by threading stores, or I/O streams, or exception continuations in and out of all computations

25 25Cs510 FSC Winter 2005 The standard morphisms Return : creates a simple (nullary) action which does nothing Bind: sequences two actions Non-standard morphisms describe the actions of the monad

26 26Cs510 FSC Winter 2005 Monads in MetaML Uses both HHTC and local polymorphism datatype ('m : * -> * ) monad = Mon of (['a]. 'a -> 'a 'm) * (['a,'b]. ('a 'm) -> ('a -> 'b 'm) -> 'b 'm); type 'x Id = 'x; val Id = (Mon (fn x => x, fn x => fn f => f x)) : Id Monad;

27 27Cs510 FSC Winter 2005 Do and Return MetaML’s interface to the standard morphisms unit and bind val ex = let fun bind (SOME x) f = f x | bind NONE f = NONE in (Mon(SOME,bind)) : option Monad end; fun option f x = Do ex { z <- x ; Return ex (f z) }; vs fun option f x = bind x (fn z => unit (f z));

28 28Cs510 FSC Winter 2005 Syntactic Sugar Do (Mon(unit,bind)) { x <- e; f } = bind e (fn x => f) Return (Mon(unit,bind)) e = unit e Do m { x1 <- e1; x2 <- e2 ; x3 <- e3 ; e4 } = Do m { x1 <- e1; Do m { x2 <- e2 ; Do m { x3 <- e3 ; e4 }}}

29 29Cs510 FSC Winter 2005 Output Monad again datatype 'a OP = OP of 'a * string; fun return x = OP(x,""); fun bind (OP(x,s1)) g = let val OP(y,s2) = g x in OP(y,s1^s2) end; val om = Mon(return,bind);

30 30Cs510 FSC Winter 2005 Error (option) Monad again val em = let fun return x = SOME x; fun bind (SOME x) g = g x | bind NONE g = NONE; in Mon(return,bind) end;

31 31Cs510 FSC Winter 2005 Multiple values (list) Monad again val mvm = let fun return x = [x]; fun mapp f [] = [] | mapp f (x::xs) = (f x) @ (mapp f xs); fun bind xs g = mapp g xs; in Mon(return,bind) end;

32 32Cs510 FSC Winter 2005 The interpreter one more time (* eval4: ‘m Monad -> Exp -> (string * int ‘m ) list -> int ‘m *) fun eval4 m exp env = case exp of Constant n => Return m n | Variable s => lookup s env | Minus(x,y) => Do m { a <- eval4 m x env ; b <- eval4 m y env ; Return m (a - b) } | Greater(x,y) => Do m { a <- eval4 m x env ; b <- eval4 m y env ; Return m (if a '>' b then 1 else 0) } | Times(x,y) => Do m { a <- eval4 m x env ; b <- eval4 m y env ; Return m (a * b) }

33 33Cs510 FSC Winter 2005 Examples val term = (Minus (Variable "x",Variable "y")) val envMVM = [("x",[9,5]),("y",[2,4])] val ans1 = eval4 mvm term envMVM; val it = [7,5,3,1] : int list val envEM = [("x",SOME 4),("y",SOME 2)] val ans2 = eval4 em term envEM; val it = SOME 2 : int option

34 34Cs510 FSC Winter 2005 Interp, one more time fun interp4 m stmt env = case stmt of Assign(name,e) => Do m { v <- eval4 m e env ; Return m(set name (Return m v) env) } | Seq(s1,s2) => Do m { env1 <- interp4 m s1 env ; interp4 m s2 env1 } | If(e,s1,s2) => Do m { x <- eval4 m e env ; if x=1 then interp4 m s1 env else interp4 m s2 env } | While(e,body) => let fun loop env = Do m { v <- eval4 m e env ; if v=0 then Return m env else Do m { env1 <- interp4 m body env; loop env1 }} in loop env end | Declare(nm,e,stmt) => Do m { v <- eval4 m e env ; env2 <- interp4 m stmt (ext nm (Return m v) env) ; Return m (remove env2) } ;

35 35Cs510 FSC Winter 2005 All features at once Now making an interpreter with all the features is easy Define a new monad with all the features Add a few new cases for Print and Divide Write a few non-standard morphisms Inject some new output for print Raise an error for divide by zero

36 36Cs510 FSC Winter 2005 New Monad datatype 'a M = M of (('a list) option) * string; fun return x = M(SOME[x],""); fun mapp f [] = M(SOME[],"") | mapp f (x::xs) = (case f x of M(NONE,s) => M(NONE,s) | M(SOME ys,s1) => (case mapp f xs of M(SOME zs,s2) => M(SOME(ys @ zs),s1^s2) | M(NONE,s2) => M(NONE,s1^s2))) fun bind (M(NONE,s)) g = M(NONE,s) | bind (M(SOME xs,s1)) g = let val M(zs,s2) = mapp g xs in M(zs,s1^s2) end val m = Mon(return,bind);

37 37Cs510 FSC Winter 2005 Non-Standard morphisms fun output s = M(SOME[s],s); fun fail s = M(NONE,s);

38 38Cs510 FSC Winter 2005 Ultimate interpreter (* eval5 : Exp -> (string * int M) list -> int M *) fun eval5 exp env = case exp of Constant n => Return m n | Variable s => lookup s env | Minus(x,y) => Do m { a <- eval5 x env ; b <- eval5 y env ; Return m (a - b) } | Greater(x,y) => Do m { a <- eval5 x env ; b <- eval5 y env ; Return m (if a '>' b then 1 else 0)} | Times(x,y) => Do m { a <- eval5 x env ; b <- eval5 y env ; Return m (a * b) } | Divide(x,y) => Do m { a <- eval5 x env ; b <- eval5 y env ; if b = 0 then fail "Divide by 0" else Return m (a div b) }

39 39Cs510 FSC Winter 2005 interp5 (* interp5 : Com -> (string * int M) list -> (string * int M) list M *) fun interp5 stmt env = case stmt of Assign(name,e) => Do m { v <- eval5 e env; Return m(set name (Return m v) env) } | Seq(s1,s2) => Do m { env1 <- interp5 s1 env; interp5 s2 env1 } | If(e,s1,s2) => Do m { x <- eval5 e env ; if x=1 then interp5 s1 env else interp5 s2 env } | While(e,body) => let fun loop env = Do m { v <- eval5 e env ; if v=0 then Return m env else Do m { env1 <- interp5 body env ; loop env1 }} in loop env end

40 40Cs510 FSC Winter 2005 Interp5 continued (* interp5 : Com -> (string * int M) list -> (string * int M) list M *) fun interp5 stmt env = case stmt of... | Declare(nm,e,stmt) => Do m { v <- eval5 e env ; env2 <- interp5 stmt (ext nm (Return m v) env) ; Return m (remove env2) } | Print(s,e) => Do m { v <- eval5 e env ; output (s^" "^(show v)) ; Return m env }


Download ppt "Tim Sheard Oregon Graduate Institute Lecture 6: Monads and Interpreters CSE 510 Section FSC Winter 2004 Winter 2004."

Similar presentations


Ads by Google