Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advanced Functional Programming Tim Sheard 1 Lecture 18 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture.

Similar presentations


Presentation on theme: "Advanced Functional Programming Tim Sheard 1 Lecture 18 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture."— Presentation transcript:

1 Advanced Functional Programming Tim Sheard 1 Lecture 18 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture 18: MetaML Examples Staged Pattern Matching Staaged interpreter MetaML extensions

2 Advanced Functional Programming Tim Sheard 2 Lecture 18 Synopsis MetaML features Pattern based object code templates templates “look like” the object language Object-code has a type. The type of code is embedded in the meta-lang type system Object code has structure. Possible to analyze it, take it apart, etc. Automatic alpha-renaming of bound variables No name clashes Object-code can be run or executed (runtime code- gen.) Object-code can be observed (pretty-printed)

3 Advanced Functional Programming Tim Sheard 3 Lecture 18 An example: Staged Pattern Matching Consider an algebra of terms Terms have constants (like 5), and operators (like +) Patterns are like terms, Except they also include variables datatype 'a Structure = Op of ('a * string * 'a) (* e.g. (1 + 5) *) | Int of int; (* e.g. 5 *) datatype term = Wrap of term Structure; datatype pat = Var of string | Term of pat Structure;

4 Advanced Functional Programming Tim Sheard 4 Lecture 18 Rewrite Rules A rewrite rule is encoded as a pair of patterns (x + y) + z --> x + (y + z) ( Term(Op(Term (Op(Var "x","+",Var "y")), "+", Var "z")), Term(Op(Var "x", "+", Term(Op(Var "y","+",Var "z")))) )

5 Advanced Functional Programming Tim Sheard 5 Lecture 18 A rule “Compiles” into a program with type: term -> term (x + y) + z --> x + (y + z) (fn Wrap a => (case a of Op(d,c,b) => if "+" %= c then (case %unWrap d of Op(g,f,e) => if "+" %= f then Wrap (Op(g,"+", Wrap (Op(e,"+",b)))) else Wrap a | _ => Wrap a) else Wrap a | _ => Wrap a))

6 Advanced Functional Programming Tim Sheard 6 Lecture 18 Simple but inefficient solution (* rewrite: pat * pat -> term -> term *) fun rewrite (lhs,rhs) term = case match lhs emptySubst term of NONE => term | SOME sigma => substitute sigma rhs Where match does a simultaneous walk over lhs and term and builds a substitution. A substitution can either fail ( NONE ) or succeed ( SOME sigma ) with a set of bindings sigma.

7 Advanced Functional Programming Tim Sheard 7 Lecture 18 fun match pat msigma (term as (Wrap t)) = case (msigma) of NONE => NONE | SOME (sigma) => (case pat of Var u => (case find u sigma of NONE => SOME ((u,term) :: sigma) | SOME w => if termeq w term then SOME sigma else NONE) | Term(Int n) => (case t of Int u => if u=n then msigma else NONE | _ => NONE) | Term(Op(t11,s1,t12)) => (case t of Op (t21,s2,t22) => (if s2 = s1 then (match t11 (match t12 msigma t22) t21) else NONE) | _ => NONE)

8 Advanced Functional Programming Tim Sheard 8 Lecture 18 Alternate, efficient Solution fun rewrite (lhs,rhs) term = case match lhs emptySubst term of NONE => term | SOME sigma => substitute sigma rhs (* rewrite: pat * pat -> term -> term *) fun rewrite (lhs,rhs) term = match2 lhs emptySubst term (fn NONE => term | SOME sigma => substitute sigma rhs) Rather than returning a substitution, match is passed a continuation which expects a subsitution, and match applies the continuation to get the answer

9 Advanced Functional Programming Tim Sheard 9 Lecture 18 fun match2 pat msigma (term as (Wrap t)) k = case (msigma) of NONE => k NONE | SOME (sigma) => (case pat of Var u => (case find u sigma of NONE => k (SOME ((u,term) :: sigma)) | SOME w => if termeq w term then k (SOME sigma) else k NONE) | Term(Int n) => (case t of Int u => if u=n then k msigma else k NONE | _ => k NONE) | Term(Op(t11,s1,t12)) => (case t of Op (t21,s2,t22) => (if s2 = s1 then match2 t11 msigma t21 (fn sigma2 => match2 t12 sigma2 t22 k) else k NONE) | _ => k NONE));

10 Advanced Functional Programming Tim Sheard 10 Lecture 18 Finally: stage the result Work with pieces of code with type term rather than terms themselves. type substitution = ((string * ) list) option; match: pat -> substitution -> -> (substitution -> ) -> rewrite:(pat * pat ) -> term>

11 Advanced Functional Programming Tim Sheard 11 Lecture 18 Staged match function fun match pat msigma term k = case (msigma) of NONE => k NONE | SOME (sigma) => (case pat of Var u => (case find u sigma of NONE => k (SOME ((u,term) :: sigma)) | SOME w => <if termeq ~w ~term then ~(k (SOME sigma)) else ~(k NONE)>) |...

12 Advanced Functional Programming Tim Sheard 12 Lecture 18 Staged match (continued)... | Term(Int n) => <case ~term of Int u => if u= ~(lift n) then ~(k msigma) else ~(k NONE) | _ => ~(k NONE)> | Term(Op(p11,s1,p12)) => <case ~term of Op(t21,s2,t22) => if ~(lift s1) = s2 then ~(match p11 msigma (fn msig => match p12 msig k)) else ~(k NONE) | _ => ~(k NONE)> );

13 Advanced Functional Programming Tim Sheard 13 Lecture 18 Staged rewrite (* rewrite :(pat * pat ) -> term> *) fun rewrite (lhs,rhs) = ~(match3 lhs (SOME []) (fn NONE => | SOME s => subst s rhs) )>;

14 Advanced Functional Programming Tim Sheard 14 Lecture 18 Applying the staging “Compiling” a rule is now simply applying the staged rewrite function to a rule. -| rewrite r3; val it = (case a of Op(d,c,b) => if "+" %= c then (case %unWrap d of Op(g,f,e) => if "+" %= f then Wrap (Op(g,"+",Wrap (Op(e,"+",b)))) else Wrap a | _ => Wrap a) else Wrap a | _ => Wrap a))> : term >

15 Advanced Functional Programming Tim Sheard 15 Lecture 18 Using Metaml MetaML can be downloaded from http://www.cse.ogi.edu/PacSoft/projects/metaml/index.html

16 Advanced Functional Programming Tim Sheard 16 Lecture 18 MetaML’s extensions to ML Staging extensions bracket, escape ~(…), lift(…), and run(…) Extensions to the type system Higher order type constructors Polymorphic components to Constructors (limited rank2 polymorphism) Qualified types (extensions to records) Syntactic extensions Monadic Do and Return Extensible records

17 Advanced Functional Programming Tim Sheard 17 Lecture 18 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))));

18 Advanced Functional Programming Tim Sheard 18 Lecture 18 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 )

19 Advanced Functional Programming Tim Sheard 19 Lecture 18 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 = []}

20 Advanced Functional Programming Tim Sheard 20 Lecture 18 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 )

21 Advanced Functional Programming Tim Sheard 21 Lecture 18 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

22 Advanced Functional Programming Tim Sheard 22 Lecture 18 The standard morphisms Unit : creates a simple (nullary) action which does nothing Bind: sequences two actions Non-standard morphisms describe the actions of the monad

23 Advanced Functional Programming Tim Sheard 23 Lecture 18 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;

24 Advanced Functional Programming Tim Sheard 24 Lecture 18 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));

25 Advanced Functional Programming Tim Sheard 25 Lecture 18 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 }}}

26 Advanced Functional Programming Tim Sheard 26 Lecture 18 State Transformer Monad datatype 'a intSt = C of (int -> ('a * int)); val intSt = let fun unit x = C(fn n => (x,n)) fun bind (C x) f = C (fn n => let val (a,n1) = x n val (C g) = f a in g n1 end) in (Mon(unit,bind)) end; Note how the state is threaded in and out of each computation.

27 Advanced Functional Programming Tim Sheard 27 Lecture 18 Using staging to write a compiler We will write a compiler using the following process. 1 - Create a denotational semantics for the language 2 - Express the semantics in terms of a monad 3 - Express the “actions” of the compiler as non-standard morphisms of the monad. 4 - Stage the monadic interpretor

28 Advanced Functional Programming Tim Sheard 28 Lecture 18 The While-language 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 *) datatype Com = Assign of (string * Exp) (* x := 1 *) | Seq of (Com * Com) (* { x := 1; y := 2 } *) | Cond 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 Exp; (* print x *)

29 Advanced Functional Programming Tim Sheard 29 Lecture 18 Semantics of While-language Exp - an environment to value function an environment is mapping from variables to values Var - reads the store Com - a function that given an environment produces a new environment and also produces output Declare - increase the size of the environment - environment behaves like a stack! Assign - change the environment Print - add something to the output - output behaves like a stream

30 Advanced Functional Programming Tim Sheard 30 Lecture 18 1 stage meaning type variable = string; type value = int; type output = string type env = variable -> value; eval : Exp -> env -> value interp : Com -> env -> (env * output)

31 Advanced Functional Programming Tim Sheard 31 Lecture 18 2 stage meaning Divide the environment into 2 pieces static part (known at compile-time) type location = int; type index = variable list; (* position in list encodes where variable lives in the stack *) dynamic part (known at run-time) type value = int type stack = value list; Meaning eval : Exp -> index -> (stack -> value) interp : Com -> index -> stack -> (stack * output)

32 Advanced Functional Programming Tim Sheard 32 Lecture 18 Creating a Monad Note the dynamic meanings of Exp and Com eval : Exp -> index -> (stack -> value) interp : Com -> index -> stack -> (stack * output) Abstract over both these with the following datatype ‘a M = StOut of (stack -> (‘a * stack * output)); eval : Exp -> index -> value M interp: Com -> index -> unit M Note that M is the type constructor of a monad.

33 Advanced Functional Programming Tim Sheard 33 Lecture 18 Monad of state with output datatype 'a M = StOut of (int list -> ('a * int list * string)); fun unStOut (StOut f) = f; fun unit x = StOut(fn n => (x,n,"")); fun bind (e : ‘a M) (f : ‘a -> ‘b M) = StOut(fn n => let val (a,n1,s1) = (unStOut e) n val (b,n2,s2) = unStOut(f a) n1 in (b,n2,s1 ^ s2) end); val mswo : M Monad = Mon(unit,bind);

34 Advanced Functional Programming Tim Sheard 34 Lecture 18 Actions in the Monad (* read : location -> int M *) fun read i = StOut(fn ns => (fetch i ns,ns,"")); (* write : location -> int -> unit M *) fun write i v = StOut(fn ns =>( (), put i v ns, "" )); (* push: int -> unit M *) fun push x = StOut(fn ns => ( (), x :: ns, "")); (* pop : unit M *) val pop = StOut(fn (n::ns) => ((), ns, "")); (* output: int -> unit M *) fun output n = StOut(fn ns =>((),ns, (toString n)^" "));

35 Advanced Functional Programming Tim Sheard 35 Lecture 18 Example translation read : location -> int M write : location -> int -> unit M push: int -> unit M pop : unit M output: int -> unit M declare x = 5 in print (x+x) do M { push 5 ; x <- read xloc ; y <- Return M (x + x) ; output y ; pop }

36 Advanced Functional Programming Tim Sheard 36 Lecture 18 Monadic eval fun eval1 exp index = (* eval1: Exp -> index -> int M *) case exp of Constant n => Return mswo n | Variable x => let val loc = position x index in read loc end | Minus(x,y) => Do mswo { a <- eval1 x index ; b <- eval1 y index; Return mswo (a - b) } | Greater(x,y) => Do mswo { a <- eval1 x index ; b <- eval1 y index; Return mswo (if a '>' b then 1 else 0) } | Times(x,y) => Do mswo { a <- eval1 x index ; b <- eval1 y index; Return mswo (a * b) };

37 Advanced Functional Programming Tim Sheard 37 Lecture 18 Monadic interp (* interp1 : Com -> index -> unit M *) fun interp1 stmt index = case stmt of Assign(name,e) => let val loc = position name index in Do mswo { v <- eval1 e index ; write loc v } end | Seq(s1,s2) => Do mswo { x <- interp1 s1 index; y <- interp1 s2 index; Return mswo () } | Cond(e,s1,s2) => Do mswo { x <- eval1 e index; if x=1 then interp1 s1 index else interp1 s2 index }

38 Advanced Functional Programming Tim Sheard 38 Lecture 18 Monadic interp (cont.) | While(e,body) => let fun loop () = Do mswo { v <- eval1 e index ; if v=0 then Return mswo () else Do mswo { interp1 body index ; loop () } } in loop () end | Declare(nm,e,stmt) => Do mswo { v <- eval1 e index ; push v ; interp1 stmt (nm::index); pop } | Print e => Do mswo { v <- eval1 e index; output v };

39 Advanced Functional Programming Tim Sheard 39 Lecture 18 2-stage Monadic eval fun eval2 exp index = (* eval2: Exp -> index -> *) case exp of Constant n => | Variable x => let val loc = position x index in end | Minus(x,y) => <Do mswo { a <- ~(eval2 x index) ; b <- ~(eval2 y index); Return mswo (a - b) }> | Greater(x,y) => <Do mswo { a <- ~(eval2 x index) ; b <- ~(eval2 y index); Return mswo (if a '>' b then 1 else 0) }> | Times(x,y) => <Do mswo { a <- ~(eval2 x index) ; b <- ~(eval2 y index) ; Return mswo (a * b) }> ;

40 Advanced Functional Programming Tim Sheard 40 Lecture 18 2-stage Monadic interp (* interpret2 : Com -> index -> *) fun interpret2 stmt index = case stmt of Assign(name,e) => let val loc = position name index in <Do mswo { n <- ~(eval2 e index) ; write ~(lift loc) n }> end | Seq(s1,s2) => <Do mswo { x <- ~(interpret2 s1 index); y <- ~(interpret2 s2 index); Return mswo () }> | Cond(e,s1,s2) => <Do mswo { x <- ~(eval2 e index); if x=1 then ~(interpret2 s1 index) else ~(interpret2 s2 index)}>

41 Advanced Functional Programming Tim Sheard 41 Lecture 18 2-stage interp (cont.) | While(e,body) => <let fun loop () = Do mswo { v <- ~(eval2 e index); if v=0 then Return mswo () else Do mswo { q <- ~(interpret2 body index); loop ()} } in loop () end> | Declare(nm,e,stmt) => <Do mswo { x <- ~(eval2 e index) ; push x ; ~(interpret2 stmt (nm::index)) ; pop }> | Print e => <Do mswo { x <- ~(eval2 e index) ; output x }>;

42 Advanced Functional Programming Tim Sheard 42 Lecture 18 declare x = 10 in { x := x - 1; print x } <Do %mswo { %push 10 ; a <- %read 1 ; b <- Return %mswo a %- 1 ; c <- %write 1 b ; d <- %read 1 ; e <- %output d ; Return %mswo () ; %pop }>

43 Advanced Functional Programming Tim Sheard 43 Lecture 18 Analyzing code Matching against code -| fun is5 = true | is5 _ = false; val is5 = fn : -> bool -| is5 (lift (1+4)); val it = true : bool -| is5 ; val it = false : bool

44 Advanced Functional Programming Tim Sheard 44 Lecture 18 Variables in code patterns -| fun parts = SOME(x,y) | parts _ = NONE; val parts = fn : -> ( * ) option -| parts ; val it = SOME (, ) : ( * ) option -| parts ; val it = NONE : ( * ) option

45 Advanced Functional Programming Tim Sheard 45 Lecture 18 Higher-order code variables Esc in pattterns under a lambda need to be higher- order variables. -| fun f ~(g ) + 0> = ~(g )> | f x = x; val f = Fn : ['b]. int> -> int> -| f (x-4) + 0>; val it = a %- 4)> : int>

46 Advanced Functional Programming Tim Sheard 46 Lecture 18 Rules for higher-order variables The escaped expression must me an application The application must have a variable as the function part. This variable is the the higher-order variable The arguments to the application must be bracketed variables which are bound in enclosing lambda expresions. All lambda bound variables must appear. Examples: ~(f )> legal ~(f )> illegal ~f > illegal fn y => ~(f )> illegal ~(f )> legal


Download ppt "Advanced Functional Programming Tim Sheard 1 Lecture 18 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture."

Similar presentations


Ads by Google