1 / 68

Introduction to ML

Introduction to ML. You will be responsible for learning ML on your own. Today I will cover some basics Read Robert Harper’s notes on “an introduction to ML” See course webpage for pointers and info about how to get the software. Intro to ML. Highlights Functional Language

arleen
Download Presentation

Introduction to ML

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introduction to ML • You will be responsible for learning ML on your own. • Today I will cover some basics • Read Robert Harper’s notes on “an introduction to ML” • See course webpage for pointers and info about how to get the software

  2. Intro to ML • Highlights • Functional Language • Functions are pervasive: • First-class values • Storable, arguments, results, nested • Strongly-typed language • Every expression has a type • Certain errors cannot occur • Polymorphic types provide flexibility • Flexible Module System • Abstract Types • Higher-order modules (functors)

  3. Intro to ML • Interactive Language • Type in expressions • Evaluate and print type and result • Compiler as well • High-level programming features • Data types • Pattern matching • Exceptions • Mutable data discouraged

  4. Preliminaries • Read – Eval – Print – Loop - 3 + 2;

  5. Preliminaries • Read – Eval – Print – Loop - 3 + 2; > 5: int

  6. Preliminaries • Read – Eval – Print – Loop - 3 + 2; > 5: int - it + 7; > 12 : int

  7. Preliminaries • Read – Eval – Print – Loop - 3 + 2; > 5: int - it + 7; > 12 : int - it – 3; > 9 : int - 4 + true; Type clash in : 3 + true Looking for a : int Type I have found a : bool Error

  8. Preliminaries • Read – Eval – Print – Loop - 3 + 2; > 5: int - it + 7; > 12 : int - it – 3; > 9 : int - 4 + true; Type clash in : 3 + true Looking for a : int Type I have found a : bool Error - 3 div 0; Failure : Div - run-time error

  9. Basic Values - (); > () : unit => like “void” in C (sort of) => the uninteresting value/type - true; > true : bool - false; > false : bool - if it then 3+2 else 7; “else” clause is always necessary > 7 : int - false andalso loop_Forever; > false : bool and also, or else short-circuit eval

  10. Basic Values Integers - 3 + 2 > 5 : int - 3 + (if not true then 5 else 7); > 10 : int No division between expressions and statements Strings - “Dave” ^ “ “ ^ “Walker”; > “Dave Walker” : string - print “foo\n”; foo > 3 : int Reals - 3.14; > 3.14 : real

  11. Using SML/NJ • Interactive mode is a good way to start learning and to debug programs, but… • Type in a series of declarations into a “.sml” file - use “foo.sml” [opening foo.sml] … list of declarations with their types

  12. Larger Projects • SML has its own built in interactive “make” • Pros: • It automatically does the dependency analysis for you • No crazy makefile syntax to learn • Cons: • May be more difficult to interact with other languages or tools

  13. Compilation Manager sources.cm a.sig b.sml c.sml Group is a.sig b.sml c.sml • % sml • OS.FileSys.chDir “~/courses/510/a2”; • CM.make(); looks for “sources.cm”, analyzes dependencies • [compiling…] compiles files in group • [wrote…] saves binaries in ./CM/ • - CM.make’“myproj/”(); specify directory

  14. What is next? • ML has a rich set of structured values • Tuples: (17, true, “stuff”) • Records: {name = “Dave”, ssn = 332177} • Lists: 3::4::5::nil or [3,4]@[5] • Datatypes • Functions • And more! • Rather than list all the details, we will write a couple of programs

  15. 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

  16. An interpreter compilers COS 320 US! lexing/ parsing evaluate print stream of characters abstract syntax abstract value stream of characters

  17. A little language (LL) • An arithmetic expression e is • a boolean value • an if statement (if e1 then e2 else e3) • the number zero • the successor of a number • the predecessor of a number • a test for zero (isZero e)

  18. LL abstract syntax in ML datatype term = Bool of bool | If of term * term * term | Zero | Successor of term | Predecessor of 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

  19. LL abstract syntax in ML If (Bool true, Zero, Successor (Successor Zero)) represents “if true then 0 else succ(succ 0)” If Suc. Bool true Zero Suc. Zero

  20. Function declarations function name function parameter fun isNumberValue t = case t of Zero => true | Successor t2 => true | _ => false default pattern matches anything

  21. What is the type of the parameter t? Of the function? function name function parameter fun isNumberValue t = case t of Zero => true | Successor t2 => true | _ => false default pattern matches anything

  22. What is the type of the parameter t? Of the function? fun isNumberValue (t:term) : bool = case t of Zero => true | Successor t2 => true | _ => false val isNumberValue : term -> bool ML does type inference => you need not annotate functions yourself (but it can be helpful)

  23. A type error fun isNumberValue t = case t of Zero => 0 | Successor t2 => true | _ => false line 22 line 25 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: Successor t2 => true

  24. A type error Actually, ML will 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: Successor 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

  25. A very subtle error fun isNumberValue t = case t of zero => true | Successor t2 => true | _ => false The code above type checks. But when we test it refined the function always returns “true.” What has gone wrong?

  26. A very subtle error fun isNumberValue t = case t of zero => true | Successor t2 => true | _ => false The code above type checks. But when we test it refined the function always returns “true.” What has gone wrong? -- zero is not capitalized -- ML treats it like a variable pattern (matches anything!)

  27. Another function fun isNumberValue t = ... fun isValue t = case t of Bool _ => true | t => isNumberValue t

  28. Exceptions exception Error of string fun debug s : unit = raise (Error s)

  29. 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

  30. Evaluator fun isNumberValue t = ... fun isValue t = ... exception NoRule fun eval1 t = case t of Bool _ | Zero => raise NoRule ...

  31. Evaluator ... fun eval1 t = case t of Bool _ | Zero => raise NoRule | If(Bool b,t2,t3) => (if b then t2 else t3) | If(t1,t2,t3) => If (eval1 t1,t2,t3) ...

  32. Evaluator exception NoRule fun eval1 t = case t of Bool _ | Zero => ... | ... | Successor t => if isValue t then raise NoRule else let val t’ = eval1 t in Successor t’ end

  33. Finishing the Evaluator fun eval1 t = case t of ... | ... | Successor t => ... | Predecessor t => ... | IsZero t => ... be sure your case is exhaustive

  34. Finishing the Evaluator fun eval1 t = case t of ... | ... | Successor t => ... What if we forgot a case?

  35. Finishing the Evaluator fun eval1 t = case t of ... | ... | Successor t => ... What if we forgot a case? ex.sml:25.2-35.12 Warning: match nonexhaustive (Bool _ | Zero) => ... If (Bool b,t2,t3) => ... If (t1,t2,t3) => ... Successor t => ...

  36. Multi-step evaluation fun eval1 t = ... fun eval t = let fun loop t = loop (eval1 t) val message = “Done\n” in ((loop t) handle NoRule => print message | Error s => print s) end Be very careful with the syntax of handle (use extra parens)

  37. ML is all about functions • There are many different ways to define functions! • I almost always use “fun f x = ...” • When I am only going to use a function once and it is not recursive, I write an anonymous function: • (fn x => ...)

  38. Anonymous functions binds a variable (n) to a value (3) val n = 3 val isNumberValue = (fn t => case t of zero => true | Successor t2 => true | _ => false) binds a variable (isNumberValue) to the anonymous function value fn keyword introduces anonymous fun

  39. Anonymous functions a type definition (very convenient) type ifun = int -> int val intCompose : ifun * ifun -> ifun = ... fun add3 x = intCompose ((fn x => x + 2), (fn y => y + 1)) x a pair of anonymous functions

  40. Anonymous functions type ifun = int -> int val intCompose : ifun * ifun -> ifun = fn (f,g) => (fn x => f (g x)) fun add3 x = intCompose ((fn x => x + 2), (fn y => y + 1)) x argument is pair of functions pattern match against arg result is a function!

  41. Another way to write a function fun f x = ........ can be written as: val f = (fn x => ......) provided the function is not recursive; f does not appear in ........

  42. Another way to write a function fun f x = .... can always be written as: val rec f = (fn x => ...f can be used here...) keyword rec declares a recursive function value

  43. Yet another way to write a function fun isNumberValue Zero = true | isNumberValue (Successor t2) = true | isNumberValue (_) = true This is just an abbreviation for fun isNumberValue t = case t of Zero => true | Successor t2 => true | _ => true

  44. Yet another way to create a type error fun isNumberValue 0 = true | isNumberValue (Successor t2) = true | isNumberValue (_) = true ex.sml:9.1-11.29 Error: parameter or result constraints of clauses don't agree [literal] this clause: term -> 'Z previous clauses: int -> 'Z in declaration: isNumberValue = (fn 0 => true | Successor t2 => true | _ => true)

  45. Parametric Polymorphism • Functions like compose work on objects of many different types val compose = fn f => fn g => fn x => f (g x) compose (fn x => x + 1) (fn x => x + 2) compose not (fn x => x < 17)

  46. Parametric Polymorphism • Functions like compose work on objects of many different types val compose = fn f => fn g => fn x => f (g x) compose not (fn x => x < 17) BAD!! compose (fn x => x < 17) not

  47. Parametric Polymorphism • Functions like compose work on objects of many different types val compose = fn f => fn g => fn x => f (g x) compose: (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b) Note: type variables are written with ‘

  48. Parametric Polymorphism • compose not : (‘c -> bool) -> (c’ -> bool) • compose not not : bool -> bool compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b) not : bool -> bool

  49. Parametric Polymorphism • compose (fn x => x) : ? compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b) not : bool -> bool

  50. Parametric Polymorphism • compose (fn x => x) : ? compose : (‘a -> ‘b) -> (‘c -> ‘a) -> (‘c -> ‘b) not : bool -> bool ‘d -> ‘d

More Related