1 / 70

New Language : ML Main topics: ML syntax Static typing, explicit data types Parameter matching

New Language : ML Main topics: ML syntax Static typing, explicit data types Parameter matching Lazy lists. Static vs. Dynamic Typing. Static Typing: Typing is (can be) done before run-time Usually at compile-time Advantage: safer C,C++,Java Dynamic Typing: Typing is done at run-time

dstump
Télécharger la présentation

New Language : ML Main topics: ML syntax Static typing, explicit data types Parameter matching

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. New Language: ML Main topics: ML syntax Static typing, explicit data types Parameter matching Lazy lists

  2. Static vs. Dynamic Typing • Static Typing: Typing is (can be) done before run-time • Usually at compile-time • Advantage: safer • C,C++,Java • Dynamic Typing: Typing is done at run-time • Usually when there is no compilation phase • Scheme • ML is a functional language with static typing!

  3. ML features • Functional • Allows polymorphic and recursive user defined datatypes • Supports static type inference • Types can either be explicitly defined, or inferred

  4. ML Basics In Scheme, declaration of names in the global env: (define <name> <exp>) In ML: val <name> = <exp>;

  5. Type information is optional: inferred if not given - valseconds = 60; • val seconds = 60 : int - val minutes = 60; • val minutes = 60 : int - val hours = 24; • val hours = 24 : int - seconds * minutes * hours; • val it = 86400 : int - it; • val it = 86400 : int - it*3; • val it = 259200 : int - val secInHour_times3 = it; • val secInHour_times3 = 259200 : int

  6. Functions - fn x => x*x; • val it = fn : int -> int Same as: • fn(x) => x*x; Application: - (fn(x) => x*x) 3; OR (fn(x) => x*x) (3); • val it = 9 : int • (fn x => x+1) ((fn x => x+1) 4); val it = 6 : int

  7. Types and Functions - valsquare = fn x : real => x*x; • valsquare = fn : real -> real - val square = fn x => x*x : real; • valsquare = fn : real -> real - val square = fn x : int => x*x : real; • Error: expression doesn't match constraint [tyconmismatch] expression: int constraint: real in expression: x * x: real

  8. Multiple arguments - val average = fn( x,y) => (x+y) /2.0; val average = fn : real * real -> real - average(3,5); Error: operator and operand don't agree [literal] operator domain: real * real operand: int * int in expression: average (3,5) - average(3.0,5.0); val it = 4.0 : real - val average1 = fn(x,y) => (x+y) /2; Error: operator and operand don't agree [literal] operator domain: real * real operand: real * int in expression: (x + y) / 2

  9. Tuple Datatype • real*real: The type of all real pairs. • int*real: The type of all integer-real pairs. • (real*real)*(real*real): The type of all pair of real pairs. • real*int*(int*int):A type of triplets of all real, integer and integer-pairs. • eal*(real -> int): The type of all pairs of a real number and a function from real to integers.

  10. Cont. - (1,2); • val it = (1,2) : int * int - (1,2,3); valit = (1,2,3) : int * int * int - valzeropair = (0.0,0.0); • val zeropair = (0.0,0.0) : real * real - valzero_NegOne = (0.0,~1.0); • val zero_NegOne = (0.0,~1.0) : real * real - (zeropair, zero_NegOne); • val it = ((0.0,0.0),(0.0,~1.0)) : (real * real) * (real * real) - val negpair = fn(x,y) => (~x,~y); • valnegpair = fn : int * int -> int * int

  11. String Datatype - "Monday" ^ "Tuesday"; • val it = "MondayTuesday" : string - size(it); • val it = 13 : int - val title = fn name => "Dr. " ^ name; • val title = fn : string -> string - title ("Racket”); • val it = "Dr. Racket" : string

  12. Conditionals and Booleans - val sign = fn (n) => if n>0 then 1 else if n=0 then 0 else ~1 (* n<0 *); • val sign = fn : int -> int - sign(~3); • val it = ~1 : int Arithmetic relations: <, >, <=, >=. Logic operators: andalso, orelse, not.

  13. valsize = fn(n) => if n>0 andalso n<100 then "small“ else 100 Error: types of if branches do not agree [literal] then branch: string else branch: int in expression: if (n>0) andalso (n<100) then "small" else 100

  14. Notes 1. Using - in symbol names is not allowed : it is interpreted as the - operator. valfact-iter = 3; • Error: non-constructor applied to argument in pattern: - ==> use _. 2. ML is case sensitive! 3. Order of definitions matter (see next) 4. Recursive functions require special treatment (see next)

  15. Recursive Functions • In Scheme: (define fact (lambda (n) (if (= n 0) 1 (* n (fact (- n 1))))))

  16. - val fact = fnn:int => if n=0 then 1 else n*fact(n-1); • Error: unbound variable or constructor: fact • Why?

  17. rec keyword valrec fact = fnn:int => if n=0 then 1 else n * fact(n-1); • valfact = fn : int -> int

  18. Mutual Recursion val rec isEven = fn n:int => if n=0 then true else not isOdd(n-1); and val rec isOdd = fn n:int => if n=0 then false else not isEven(n-1);

  19. Patterns in Function Arguments - val rec fact = fn 0 => 1 | n => n * fact(n-1); val fact = fn : int -> int - val rec fact = fn0 => 1 | 1 => 1 * fact(0); • Warning: match nonexhaustive 0 => ... 1 => ... val fact = fn : int -> int

  20. val rec ackermann = fn (0,b) => b+1 | (a,0) => ackermann(a-1,1) | (a,b) => ackermann(a-1, ackermann(a, b-1)); val ackermann = fn : int * int -> int

  21. “Wildcard” - val or = fn (true, _) => true | (_, true) => true | (_, _) => false; val or = fn : bool * bool -> bool

  22. High-order procedures - val rec sum = fn(term, a, next, b) => if a>b then 0 else term(a)+sum(term,next(a),next,b); valsum = fn : (int -> int) * int * (int -> int) * int-> int

  23. average_damp - val average_damp = fn f => (fn x => (x+f(x))/2.0); val average_damp = fn : (real -> real) -> real -> real

  24. let let val m : int = 3 val n : int = m*m in m * n end; valit = 27 : int

  25. val fact = let val rec iter = fn (0, result) => result | (count, result) => iter(count-1, count*result) in fn n => iter(n, 1) end; val fact = fn : int -> int

  26. Lists in ML • val rec list_length = fn(h::t) => 1+list_length(t) | nil => 0; Response: vallist_length = fn:'a list -> int :: is the value constructor (like cons in scheme) nil =[] (= scheme NULL) All elements of the list must be of the same type (homogenous list) Polymorphic type: ‘a is a type variable type string_list = string list;

  27. head and tail val head = fn h::_ => h; val tail= fn _::t => t;

  28. What about NULLs? exception Empty; val head = fn nil => raise Empty | h::_ => h; val head = fn : 'a list -> 'a

  29. Example: foldr val rec foldr = fn (f, e, []) => e | (f, e, (h :: tl) ) => f(h, foldr(f, e, tl)); • valfoldr = fn : (('a * 'b -> 'b) * 'b * 'a list) -> 'b

  30. Example: Key-value storage val rec assoc = fn (str:string, []) => 0 | (str, ((key, value)::s)) => if (str=key) then value else assoc(str, s);

  31. Adding new types Simple: Atomic User-Defined Types datatype week = Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday week is a type constructor Sunday… are the value constructors (convention: start with upper case letter)

  32. Eager list implementation datatype pair_selector_name = Car | Cdr; datatype pair_selector_name = Car | Cdr; val cons = fn(x,y) => fn Car => x | Cdr => y; fn : ('a * 'a) -> (pair_selector_name -> 'a)

  33. Composite User Defined Types • datatype address = MailBoxof int | CityCon1 of string * string * int | CityCon2 of string * string * string * int | Village of string * string; CityCon1, CityCon2, Village are the value constructors

  34. Equality predicate for addresses • valeq_address = fn(CityCon1(city, street, number), CityCon2(city', _, street', number')) => city=city' andalso street=street' andalso number = number' | (x, y) => x=y;

  35. Patterns Revisited • A powerful tool for manipulating different data types • No need for explicit predicates, selectors • Can’t be used for equality via the repeated use of the same variable name • In fact no symbol can occur twice in the pattern except for “_”

  36. Equality types • We have used “=“ to compare both ints and strings • Real.== is used for reals • “=“ is then automatically defined for complex types if defined for each of their components • Only such types can be used in patterns • If “=“ is used for a type not known to be an equality type, a warning will be issued

  37. Recursive Types • datatypeexpr = Constof real | Add of expr * expr | Sub of expr * expr | Mul of expr * expr | Div of expr * expr;

  38. Trees: Recursive Polymorphic Types datatype 'a binary_tree = Empty | Node of 'a binary_tree * 'a * 'a binary_tree; Type constructor: binary_tree Value constructors: Node (3 params), Empty (no params)

  39. (* Signature: tree_size Purpose: Calculate the size (number of nodes) in a binary tree Type: 'a binary_tree -> int *) - val rec tree_size = fn Empty => 0 | Node(lft, _, rht) => (1 + tree_size(lft) + tree_size(rht)); Response: valtree_size = fn : 'a binary_tree -> int

  40. Explicit “unioning” through constructors datatype int_or_string = Int of int | String of string; type int_or_string_binary_tree = int_or_string binary_tree;

  41. Lazy Lists

  42. Motivation (define (sum-primes a b) (define (iter count accum) (cond ((> count b) accum) ((prime? count) (iter (+ count 1) (+ count accum))) (else (iter (+ count 1) accum)))) (iter a 0)) (define (sum-primes a b) (accumulate + 0 (filter prime? (enumerate-interval a b)))) Second implementation consumes a lot of storage

  43. Motivation (Cont.) (car (cdr (filter prime? (enumerate-interval 10000 1000000)))) Requires a lot of time and space How can we gain the efficiency of iteration, and retain the elegance of sequence-operations? In ML: Lazy Lists! (Sequences)

  44. Remember scheme applicative vs. normal order evaluation? • Normal (Lazy) Order Evaluation: • go ahead and apply operator with unevaluated argument subexpressions • evaluate a subexpression only when value is needed • to print • by primitive procedure (that is, primitive procedures are "strict" in their arguments) • Compromise approach: give programmer control between normal and applicative order. • Lazy lists: lists with delays

  45. More Motivation Some data types are inherently infinite Integers, Reals,… Can we generate a list of “all” integers? YES! (if at each point we only materialize a finite prefix..)

  46. Main Idea: Delayed evaluation A list is a pair of (item, remaining list) We will generate a pair (item,promise_to_generate_remaining_list) Concrete ideas for implementation of a “promise”?

  47. Sequences in ML A list is a pair of (item, remaining list) We will generate a pair (item,promise_to_generate_remaining_list) Concrete ideas for implementation of a “promise”?

  48. Sequences datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq); Cons(1,Nil)=> error

  49. Sequences datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq); Cons(1,Nil)=> error

  50. Sequences datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq); Cons(1,Nil)=> error Cons(1, (fn() => Nil)) CORRECT

More Related