250 likes | 371 Vues
Dive into the second part of the introduction to ML with Kenny Zhu. Explore the foundational concepts of structured values including tuples, records, and lists, alongside core datatypes and functions. Learn how to build more complex programs with interpreters, covering essential processes such as lexing, parsing, and evaluation. The tutorial also explains arithmetic expressions, boolean values, and type inference in ML. Comprehensive examples illustrate how to define functions, handle exceptions, and manage source files for interpreters, as well as insights into list functions like map and fold.
E N D
Introduction to ML - Part 2 Kenny Zhu
What is next? • ML has a rich set of structured values • Tuples: (17, true, “stuff”) • Records: {name = “george”, age = 35} • Lists: 3::4::5::nil or [3,4]@[5] • Datatypes • Functions • And more! • We put things together in a more complex program
An interpreter • Interpreters are usually implemented as a series of transformers: lexing/ parsing evaluate print stream of characters abstract syntax abstract value stream of characters
A little language (LL) • An arithmetic expression e is • a boolean value • an if statement (if e1 then e2 else e3) • an integer • an add operation • a test for zero (isZero e)
LL abstract syntax in ML datatype term = Bool of bool | If of term * term * term | Num of int | Add of term * term | IsZero of term -- constructors are capitalized -- constructors can take a single argument of a particular type type of a tuple another eg: string * char vertical bar separates alternatives
LL abstract syntax in ML Add Add (Num 2, Num 3) represents the expression “2 + 3” Num Num 2 3
LL abstract syntax in ML If If (Bool true, Num 0, Add (Num 2, Num 3)) represents “if true then 0 else 2 + 3” Add Bool Num true Num Num 0 3 2
Function declarations function name function parameter fun isValue t = case t of Num n => true | Bool b => true | _ => false default pattern matches anything
What is the type of the parameter t? Of the function? function name function parameter fun isValue t = case t of Num n => true | Bool b => true | _ => false default pattern matches anything
What is the type of the parameter t? Of the function? fun isValue (t:term) : bool = case t of Num n => true | Bool b => true | _ => false val isValue : term -> bool ML does type inference => you need not annotate functions yourself (but it can be helpful)
A type error fun isValue t = case t of Num _ => 1 | _ => false ex.sml:22.3-24.15 Error: types of rules don't agree [literal] earlier rule(s): term -> int this rule: term -> bool in rule: _ => false
A type error Actually, ML may give you several errors in a row: ex.sml:22.3-25.15 Error: types of rules don't agree [literal] earlier rule(s): term -> int this rule: term -> bool in rule: Num t2 => true ex.sml:22.3-25.15 Error: types of rules don't agree [literal] earlier rule(s): term -> int this rule: term -> bool in rule: _ => false
A very subtle error fun isValue t = case t of num => true | _ => false The code above type checks. But when we test it, the function always returns “true.” What has gone wrong?
A very subtle error fun isValue t = case t of num => true | _ => false The code above type checks. But when we test it, the function always returns “true.” What has gone wrong? -- num is not capitalized (and has no argument) -- ML treats it like a variable pattern (matches anything!)
Exceptions exception Error of string fun debug s : unit = raise (Error s)
Exceptions exception Error of string fun debug s : unit = raise (Error s) in SML interpreter: - debug "hello"; uncaught exception Error raised at: ex.sml:15.28-15.35
Evaluator fun isValue t = ... exception NoRule fun eval t = case t of Bool _ | Num _ => t | ...
Evaluator ... fun eval t = case t of Bool _ | Num _ => t | If(t1,t2,t3) => let val v = eval t1 in case v of Bool b => if b then (eval t2) else (eval t3) | _ => raise NoRule end let statement for remembering temporary results
Evaluator exception NoRule fun eval1 t = case t of Bool _ | Num _ => ... | ... | Add (t1,t2) => case (eval v1, eval v2) of (Num n1, Num n2) => Num (n1 + n2) | (_,_) => raise NoRule
Finishing the Evaluator fun eval1 t = case t of ... | ... | Add (t1,t2) => ... | IsZero t => ... be sure your case is exhaustive
Finishing the Evaluator fun eval1 t = case t of ... | ... | Add (t1,t2) => ... What if we forgot a case?
Finishing the Evaluator fun eval1 t = case t of ... | ... | Add (t1,t2) => ... What if we forgot a case? ex.sml:25.2-35.12 Warning: match nonexhaustive (Bool _ | Zero) => ... If (t1,t2,t3) => ... Add (t1,t2) => ...
Demo • Managing the source files for the interpreter
More on lists: Map fun map f l = case l of nil => [] l x :: l => (f x) :: (map f l) applies the function f to every element in the list - fun add1 x = x + 1; - map add1 [1,2,3]; > val it = [2,3,4] : int list
More on lists: Fold fun fold f init l = case l of nil => init | x :: l => f (x, fold f init l) applies function f (x, y) on the elements of l and the result from previous application recursively - fun sum (x, y) = x + y; - foldr sum 0 [1,2,3,4]; val it = 10 : int