710 likes | 842 Views
A Fourth Look At ML. Additional information Programming in ML A Gentle Introduction to ML Source level debugging in Poly/ML. Download as Power Point file for saving or printing . Type Definitions. Predefined, but not primitive in ML: Type constructor for lists: Defined for ML in ML.
E N D
A Fourth Look At ML • Additional information • Programming in ML • A Gentle Introduction to ML • Source level debugging in Poly/ML Download as Power Point file for saving or printing. Modern Programming Languages - Chapter 11
Type Definitions • Predefined, but not primitive in ML: • Type constructor for lists: • Defined for ML in ML datatype bool = true | false; datatype 'element list = nil | :: of 'element * 'element list Modern Programming Languages - Chapter 11
Outline • Enumerations • Data constructors with parameters • Type constructors with parameters • Recursively defined type constructors • Farewell to ML – For a little while Modern Programming Languages - Chapter 11
Programmer Defined Types • New types can be defined using the keyword datatype • These declarations define both: • type constructors for making new (possibly polymorphic) types • data constructors for making values of those new types Modern Programming Languages - Chapter 11
Example datatype day = Mon | Tue | Wed | Thu | Fri | Sat | Sun;datatype day = Fri | Mon | Sat | Sun | Thu | Tue | Wedfun isWeekDay x = not (x = Sat orelse x = Sun);val isWeekDay = fn : day -> boolisWeekDay Mon;val it = true : boolisWeekDay Sat;val it = false : bool • day is the new type constructor and Mon, Tue, etc. are the new data constructors • Why “constructors”? In a moment we will see how both can have parameters… Modern Programming Languages - Chapter 11
No Parameters datatype day = Mon | Tue | Wed | Thu | Fri | Sat | Sun;datatype day = Fri | Mon | Sat | Sun | Thu | Tue | Wed • The type constructorday takes no parameters: it is not polymorphic, there is only one day type • The data constructorsMon, Tue, etc. take no parameters: they are constant values of the day type • Convention is to capitalize the names of data constructors Modern Programming Languages - Chapter 11
Strict Typing datatype flip = Heads | Tails;datatype flip = Heads | Tailsfun isHeads x = (x = Heads);val isHeads = fn : flip -> boolisHeads Tails; val it = false : boolisHeads Mon;Error: Can't unify flip with day (Different type constructors) Found near isHeads(Mon) operator domain: flip operand: day • ML strictly enforces operations on new types • Unlike C enum, no implementation details are exposed to the programmer. The following defines C type flip with Heads=0, Tails=1. enum flip {Heads, Tails}; Modern Programming Languages - Chapter 11
Data Constructors In Patterns fun isWeekDay Sat = false| isWeekDay Sun = false| isWeekDay _ = true; • Data constructors can be used in patterns • In this simple case, similar to constants • More general case where constructor contains a typed data item, considered next Modern Programming Languages - Chapter 11
Outline • Enumerations • Data constructors with parameters • Type constructors with parameters • Recursively defined type constructors • Farewell to ML Modern Programming Languages - Chapter 11
Datatype Parameters - Wrappers • Parameterize any type to a data constructor, using the keyword of:datatype IR = I of int | R of real; • In effect, such a constructor is a wrapper that contains a data item of the given type Modern Programming Languages - Chapter 11
Datatype Parameters - Wrappers datatype IR = I of int | R of real; I R b a 38.5 4 val a = R 38.5;val a = R 38.5 : IR R; val it = fn:real->IR R 5; error val b = I 4;val b = I 4 : IR I; val it = fn:int->IR I 3.14; error Modern Programming Languages - Chapter 11
Wrappers • You can add a parameter of any type to a data constructor, using the keyword of:datatype exint = Value of int | PlusInf | MinusInf; • In effect, such a constructor is a wrapper that contains a data item of the given type w Value x PlusInf r Value 38 36 Some things of type exint: MinusInf Value 26 q s Modern Programming Languages - Chapter 11
Wrapper Example datatype exint = Value of int | PlusInf | MinusInf; datatype exint = MinusInf | PlusInf | Value of int val s = MinusInf;val s = MinusInf : exintValue; function signatureval it = fn : int -> exintval r = Value 38;val r = Value 38 : exint • Value is a data constructor that takes a parameter: the value of the int to store • Signature is a function that takes an int and returns an exint containing that int s MinusInf Value r 38 Modern Programming Languages - Chapter 11
A Value Is extint Not int val x = Value 5;val x = Value 5 : exint x+x;Error: overloaded variable not defined at type symbol: + type: exint (Value 5) + (Value 5); Error: overloaded variable not defined at type symbol: + type: exint Value x 5 • Value 5 is an exint • It is not an int, though it contains one • The int accessed by pattern matching Modern Programming Languages - Chapter 11
Patterns With Data Constructors val x = Value 5; val x = Value 5 : exint val (Value y) = Value 5; val y = 5 : int Value x 5 • To recover a data constructor’s parameters, use pattern matching • So Value is no ordinary function: ordinary functions can't be pattern-matched this way y 5 Modern Programming Languages - Chapter 11
Exhaustive Patterns val x = Value 5;val s = case x of PlusInf => "infinity" |MinusInf => "-infinity" | Value y => Int.toString y;val s = "5" : string An exint can be a PlusInf, a MinusInf, or a Value val x = Value 5;val s = case x of PlusInf => 9999999999999999 | MinusInf => ~9999999999999999 | Value y => y; val s = 5 : int Modern Programming Languages - Chapter 11
Pattern-Matching Function fun square PlusInf = PlusInf| square MinusInf = PlusInf| square (Value x) = Value (x*x);val square = fn : exint -> exintsquare MinusInf;val it = PlusInf : exintsquare (Value 3);val it = Value 9 : exint Pattern-matching function definitions are especially important with programmer defined datatypes Modern Programming Languages - Chapter 11
Example - extint Factorial fun mult (Value x) (Value y) = Value (x*y);val mult = fn : exint -> exint -> exint mult (Value 5) (Value 4);val it = Value 20 : exint fun fact PlusInf = PlusInf | fact MinusInf = MinusInf| fact (Value 0) = Value 1| fact (Value n) = mult (fact (Value(n-1))) (Value n);val fact = fn : exint -> exint fact (Value 5);val it = Value 120 : exint Modern Programming Languages - Chapter 11
Exercise 1 • Give a datatype declaration for type constructor color with data constructor red, green, yellow, blue, white. • Define function primary that returns true when the single parameter is red, green or blue; else return false. • Give a parameterized datatype declaration for type number of integer (anInt) or real (aReal). datatype exint = Value of int | PlusInf | MinusInf; val x = aReal 5.0; val x = aReal 5.0 : number val y = anInt 4; val y = anInt 4 : number Modern Programming Languages - Chapter 11
Exercise 1 Continued • Define the function plus of type: number->number->number that adds two numbers, when adding anInt and aReal return aReal. Coerce int to real:real(3) converts int type to real. val x = aReal 5.0; val y = anInt 4; plus x y; val it = aReal 9.0 : number plus y y; val it = anInt 8 : number Modern Programming Languages - Chapter 11
Outline • Enumerations • Data constructors with parameters • Type constructors with parameters • Recursively defined type constructors • Farewell to ML Modern Programming Languages - Chapter 11
Type Constructors With Parameters • Type constructors without parameters: datatype EXINT = NOINT | SOMEINT of int; • Type constructors with parameters: datatype 'a option = NONE | SOME of 'a; • 'a the type parameter; option the datatype name • Type constructor parameters are type variables • Result: a new polymorphic type bound at execution time Modern Programming Languages - Chapter 11
Type Constructors With Parameters • Type constructors without parameters:datatype EXINT = NOINT | SOMEINT of int;NOINT; val it = NOINT : EXINTSOMEINT 12; val it = SOMEINT 12 : EXINT • Type constructors with parameters: datatype 'a option = NONE | SOME of 'a; NONE; val it = NONE : ‘a optionSOME 45; val it = SOME 45 : int option SOMEINT SOME 45 1 SOME NONE SOMEINT NOINT "world" 123 Values of type string option andint option Values of type EXINT Modern Programming Languages - Chapter 11
Parameter Before Name SOME;val it = fn : 'a -> 'a option SOME 4;val it = SOME 4 : int optionSOME 1.2;val it = SOME 1.2 : real option SOME "pig";val it = SOME "pig" : string option SOME [1,2,3]; val it = SOME [1, 2, 3] : int list option • Type constructor parameter 'a before constructor name:datatype 'a option = NONE | SOME of 'a; • Types 'a option and int option, just like 'a list and int list. Modern Programming Languages - Chapter 11
Uses of our option datatype • Predefined type constructor in ML • Used by predefined functions (or your own) when the result is not always defined fun optdiv a b =if b = 0 then NONE else SOME (a div b);val optdiv = fn : int -> int -> int optionoptdiv 7 2;val it = SOME 3 : int optionoptdiv 7 0;val it = NONE : int option Modern Programming Languages - Chapter 11
Uses of option datatype datatype 'a option = NONE | SOME of 'a; datatype exint = Value of int | PlusInf | MinusInf; val x = SOME (Value 3); val x = SOME (Value 3) : exint option SOME (SOME 5); val it = SOME (SOME 5) : int option option SOME (SOME 5, 3.14); val it = SOME (SOME 5, 3.14) : (int option * real) option Modern Programming Languages - Chapter 11
Longer Example: bunch datatype 'x bunch = One of 'x | Group of 'x list; • An 'x bunch is either one of type 'x, or a list of type 'x • As usual, ML infers types: One 1.0;val it = One 1.0 : real bunchGroup [true,false];val it = Group [true,false] : bool bunch Modern Programming Languages - Chapter 11
Example: Polymorphism datatype 'x bunch = One of 'x | Group of 'x list; fun size (One _) = 1| size (Group x) = length x;val size = fn : 'a bunch -> intsize (One 1.0);val it = 1 : intsize (Group [true, false]);val it = 2 : int • ML can infer bunch types, but does not always have to resolve them, just as with list types Modern Programming Languages - Chapter 11
Example: No Polymorphism datatype 'x bunch = One of 'x | Group of 'x list;fun sum (One x) = x| sum (Group []) = 0| sum (Group (h::t)) = h + sum (Group t);val sum = fn : int bunch -> intsum (One 5);val it = 5 : intsum (Group [1,2,3]);val it = 6 : int • Applied the + operator to the list elements • ML determines int bunch the parameter type Modern Programming Languages - Chapter 11
Exercise 2Which are valid? datatype bunch = One of int | Group of int list; • One 3; • One "Hi"; • Group [1,2,3]; • Group ["Hi", "OK"]; datatype 'x bunch = One of 'x | Group of 'x list; • One 3; • One "Hi"; • Group [1,2,3]; • Group ["Hi", 3]; • Group [One 1, One 2]; • Group [One "Hi", One 3]; • Group [Group [1,2], Group[3,4]]; • Group [Group ["Hi", "OK"], Group[1,2]]; Modern Programming Languages - Chapter 11
Fix the error. Exercise 2 datatype intbunch = One of int | Group of int list; fun sum (One i) = i | sum (Group []) = 0 | sum (Group (h::t))=(sum h)+(sum(Group t)); Are these valid? the same? datatype intbunch = One of int | Group of int list; Group[1,2,3]; datatype intbunch = One of int | Group of intbunch list; Group[One 1, One 2, One 3]; Group[One 1, Group[One 2, One 3]]; Modern Programming Languages - Chapter 11
Exercise 2 datatype intnest = INT of int | LIST of intnest list; fun intret (INT i) = i| intret (LIST [a]) = intret a | intret (LIST (h::t)) = intret (LIST t);intret (INT 9); returns 9 intret (LIST [INT 4, INT 3]); returns 3 9 INT INT INT LIST 4 3 Write function sum of type intnest that sums all integers in an intnest. sum (LIST [ INT 5, INT 4 ]); returns 9 Hint: match (INT x) and (LIST L). For (LIST L), L is a list with hd L an INT and tl L a LIST. Return 0 when L is null, otherwise sum the INT and LIST parts. Modern Programming Languages - Chapter 11
Outline • Enumerations • Data constructors with parameters • Type constructors with parameters • Recursively defined type constructors • Farewell to ML Modern Programming Languages - Chapter 11
Recursively Defined Type Constructors The type constructor being defined may be used in its own data constructors:datatype intlist = INTNIL | INTCONS of int * intlist; val x = INTNIL; Some values of type intlist: INTCONS(1,INTNIL) INTCONS(1, INTCONS(2,INTNIL)) Modern Programming Languages - Chapter 11
Construction as a Tuple datatype intlist = INTNIL | INTCONS of int * intlist; INTNIL;val it = INTNIL : intlistINTCONS (1,INTNIL);val it = INTCONS (1,INTNIL) : intlistINTCONS (1,INTCONS(2,INTNIL)); val x = INTNIL; INTCONS(1,INTNIL) INTCONS(1, INTCONS(2,INTNIL)) Modern Programming Languages - Chapter 11
An intlist Length Function datatype intlist = INTNIL | INTCONS of int * intlist; fun intListLength INTNIL = 0| intListLength (INTCONS(_,tail)) = 1 + (intListLength tail); val x = INTCONS (3, INTCONS (4, INTNIL)); intListLength x; val it = 2 : int intlist similar to predefined lists except use of INTNIL or int * intlist tuples for each element Modern Programming Languages - Chapter 11
Exercise 2.5 datatype intlist = INTNIL | INTCONS of int * intlist; fun intlistLength INTNIL = 0| intlistLength (INTCONS(_,tail)) = 1 + (intlistLength tail); Integer list sum function. fun sum [] = 0| sum (h::t) = h + sum t; Give the function to sum an intlist. sum (INTCONS (3, INTCONS (4, INTNIL))); return 7 Modern Programming Languages - Chapter 11
Parametric List Type datatype 'element mylist = NIL | CONS of 'element * 'element mylist; • A parametric list type using nested tuples, similar to predefined list • 'element is polymorphic type parameter • Allows a mylist datatype of polymorphic types CONS(1.0, NIL);val it = CONS (1.0,NIL) : real mylistCONS(1, CONS(2, NIL));val it = CONS (1,CONS (2,NIL)) : int mylist Modern Programming Languages - Chapter 11
list and mylist Functions datatype 'element mylist = NIL | CONS of 'element * 'element mylist; • Similar to predefined list type constructor fun length [] = 0 | length (_::t) = 1 + length t; length [5,2,3,6]; return 4 fun myLength NIL = 0| myLength (CONS(_,t)) = 1 + myLength t;myLength (CONS(1, CONS(2, NIL))); return 2 Modern Programming Languages - Chapter 11
list and mylist Functions datatype 'element mylist = NIL | CONS of 'element * 'element mylist; Of course, to add up a list could use foldr… fun addup [] = 0| addup (h::t) = h + addup t;addup [1,2]; return 3 fun myAddup NIL = 0| myAddup (CONS(h,t)) = h + myAddup t;myAddup (CONS(1, CONS(2, NIL))); returns 3 Modern Programming Languages - Chapter 11
A foldr for mylist fun myfoldr f c NIL = c | myfoldr f c (CONS(a,b))=f(a,myfoldr f c b);myfoldr (op +) 0 (CONS (1, CONS(2, NIL))); 3 • myfoldr works on 'a mylist • One difference: :: is an operator and CONS is not fun foldr f c [] = c | foldr f c (a::b) = f(a, foldr f c b); foldr (op +) 0 [1,2]; 3 Modern Programming Languages - Chapter 11
Exercise 3 fun map _ [] = [] | map f (h::t) = (f h)::(map f t);map (fn x => x + 1) [1,2,3];val it = [2, 3, 4] : int list • Write mymap function for a mylist. datatype 'el mylist = NIL | CONS of 'el * 'el mylist; val c = CONS(1,CONS(2,CONS(3, NIL))); val c=CONS(1,CONS(2,CONS(3,NIL))):int mylist mymap (fn x => x + 1) c; val it = CONS(2,CONS(3,CONS(4,NIL))):int mylist Modern Programming Languages - Chapter 11
Exercise 3 datatype 'el mylist = NIL | CONS of 'el * 'el mylist; val c = CONS(1,CONS(2,CONS(3, NIL))); val c=CONS(1,CONS(2,CONS(3,NIL))):int mylist fun snoc a NIL = CONS(a,NIL) | snoc a (CONS(h,t)) = CONS(h,(snoc a t)); snoc 4 (CONS(1,CONS(2,NIL))); CONS(1,CONS(2,CONS(4,NIL))):int mylist rev (CONS(1,CONS(2,NIL))); val it = CONS(2,CONS(1, NIL)) : int mylist • Write rev function to reverse a mylist. • Function snoc places an ’el at end of a mylist. Modern Programming Languages - Chapter 11
Defining Operators (A Peek) • ML allows new operators to be defined • infixr 5 CONS;defines CONS to be right-associative with precedence 5, the same as :: • Higher number equals higher precedence infixr 5 CONS;1 CONS 2 CONS NIL;val it = 1 CONS 2 CONS NIL : int mylist fun add (x, y) = x + y;fun mul (x, y) = x * y;infixr 3 add;infixr 4 mul;2 add 4 mul 5;val it = 22 : int Modern Programming Languages - Chapter 11
C++ tree Implementation struct tree { tree *left, *right; char data;};void f(tree *t) { if(t != NULL) { cout << t->data; f(t->left); f(t->right); }}void main ( void ){ tree l1={NULL,NULL,'1'}, l2={NULL,NULL,'2'}, r2={NULL,NULL,'3'}, r1={&l2,&r2,'*'}, t={&l1,&r1,'-'}; f(&t);} Output: -1*23 _ / \1 * / \ 2 3 Modern Programming Languages - Chapter 11
Java tree Implementation public class ExampleTree { static void f(tree t) { if(t != null) { System.out.println(t.data); f(t.left); f(t.right); } } public static void main ( String args[] ){ tree l1=new tree(null,null,'1'), l2=new tree(null,null,'2'), r2=new tree(null,null,'3'), r1=new tree(l2,r2,'*'), t=new tree(l1,r1,'-'); f(t); } } class tree { public tree left, right; public char data; public tree(tree left, tree right, char data) { this.left=left; this.right=right; this.data=data; } }; Output: -1*23 _ / \1 * / \ 2 3 Modern Programming Languages - Chapter 11
Java tree Implementation datatype 'data tree = Empty | Node of 'data tree * 'data * 'data tree; val l1=Node(Empty,"1",Empty); val l2=Node(Empty,"2",Empty); val r2=Node(Empty,"3",Empty); val r1=Node(l2,"*",r2); val t=Node(l1,"-",r1); fun f Empty = "" | f (Node (l,d,r)) = d ^ f l ^ f r; f t; Output: -1*23 _ / \1 * / \ 2 3 Modern Programming Languages - Chapter 11
Polymorphic Binary Tree datatype 'data tree = Empty | Node of 'data tree * 'data * 'data tree; Some values of type int tree: Modern Programming Languages - Chapter 11
Constructing Those Values val treeEmpty = Empty;val treeEmpty = Empty : 'a treeval tree2 = Node(Empty,2,Empty);val tree2 = Node (Empty,2,Empty) : int treeval tree123 = Node(Node(Empty,1,Empty),2, Node(Empty,3,Empty)); 2 1 3 Empty Empty Empty Empty Modern Programming Languages - Chapter 11
Increment All Elements fun incall Empty = Empty | incall (Node(x,y,z)) = Node(incall x, y+1, incall z); incall tree123;val it = Node (Node (Empty,2,Empty), 3, Node (Empty,4,Empty)) : int tree 3 2 4 Empty Empty Empty Empty Modern Programming Languages - Chapter 11