Types in ML Ch 11 n Predefined but
Types in ML (Ch 11) n Predefined, but not primitive in ML: datatype bool = true | false; Type constructor for lists: nil, [1, 2, 3, 4], [″a”, ″b”] datatype 'element list = nil | : : of 'element * 'element list We are going to learn what is that! 10/25/2020 IT 327 1
Defining Your Own Types n New types can be defined using the keyword datatype n These declarations define both: – – 10/25/2020 type constructors for making new (possibly polymorphic) types data constructors for making values of those new types IT 327 2
Enumeration examples -datatype day = Mon | Tue | Wed | Thu | Fri | Sat | Sun; datatype day = Fri | Mon | Sat | Sun | Thu | Tue | Wed - fun is. Week. Day x = not (x = Sat orelse x = Sun); val is. Week. Day = fn : day -> bool - is. Week. Day Mon; val it = true : bool - is. Week. Day Sat; val it = false : bool n n n day is the new type constructor Mon, Tue, etc. are the new data constructors Why call them “constructors”? Since both can have parameters… 10/25/2020 IT 327 3
No Parameters involved - datatype day = Mon | Tue | Wed | Thu | Fri | Sat | Sun; datatype day = Fri | Mon | Sat | Sun | Thu | Tue | Wed n The type constructor day takes no parameters: it is not polymorphic, there is only one day type n The data constructors Mon, Tue, etc. take no parameters: they are constant values of the day type 10/25/2020 IT 327 4
Strict Typing - datatype flip = Heads | Tails; datatype flip = Heads | Tails - fun is. Heads x = (x = Heads); val is. Heads = fn : flip -> bool - is. Heads Tails; val it = false : bool - is. Heads Mon; Error: operator and operand don't agree [tycon mismatch] operator domain: flip operand: day n n ML is strict about types, Unlike C enum, no implementation details are exposed to the programmer 10/25/2020 IT 327 5
Data Constructors in Patterns fun is. Week. Day Sat = false | is. Week. Day Sun = false | is. Week. Day _ = true; You can use the data constructors in patterns n They are like constants n 10/25/2020 IT 327 6
Data constructors with parameters Wrappers type constructor 3 data constructors Add a parameter of any type to a data onstructor, using the keyword of datatype exint = Value of int | Plus. Inf | Minus. Inf; Such a constructor is a wrapper that contains a data item of the given type Exint examples: 10/25/2020 Value Plus. Inf Value 38 Minus. Inf IT 327 36 Value 26 7
- datatype exint = Value of int | Plus. Inf | Minus. Inf; datatype exint = Minus. Inf | Plus. Inf | Value of int -Plus. Inf; val it = Plus. Inf : exint - Minus. Inf; val it = Minus. Inf : exint - Value; val it = fn : int -> exint - Value 3; val it = Value 3 : exint n n 10/25/2020 Value is a data constructor that takes a parameter that is a value of int It is a special kind of function int -> exint IT 327 8
A Value is Not an int - val x = Value 5; val x = Value 5 : exint - x+x; Error: overloaded variable not defined at type symbol: + type: exint n Value 5 is an exint n It is not an int, though it contains one n How can we get the int out? 10/25/2020 IT 327 9
Patterns With Data Constructors Pattern matching can retrieve data constructor’s parameters val x = Value 5; - - val (Value y) = x; Warning: binding not exhaustive Value y =. . . val y = 5 : int n exint So Value is no ordinary function: ordinary functions can't be pattern-matched 10/25/2020 IT 327 10
An Exhaustive Pattern - val s = case x of = Plus. Inf => "infinity" | = Minus. Inf => "-infinity" | = Value y => Int. to. String y; val s = "5" : string n n n You get a warning if it is not exhaustive An exint can be a Plus. Inf, a Minus. Inf, or a Value This one does not all cases should be considered Consider all cases - val (Value y) = x; Warning: binding not exhaustive Value y =. . . val y = 5 : int 10/25/2020 IT 327 11
Similar bindings (matching) that are not exhaustive - val x = Value 5; - val (Value y) = x; Warning: binding not exhaustive Value y =. . . val y = 5 : int - val [a, b] = [1, 2]; std. In: 1. 4 -1. 18 Warning: binding not exhaustive a : : b : : nil =. . . val a = 1 : int val b = 2 : int 10/25/2020 IT 327 12
Pattern-Matching Function -fun square Plus. Inf = | square Minus. Inf = Plus. Inf = | square (Value x)= Value (x*x); val square = fn : exint -> exint - square Minus. Inf; val it = Plus. Inf : exint - square (Value 3); val it = Value 9 : exint 10/25/2020 IT 327 13
Exception Handling -fun square Plus. Inf = | square Minus. Inf = Plus. Inf = | square (Value x) = Value (x*x) = handle Overflow => Plus. Inf; val square = fn : exint -> exint - square (Value 10000); val it = Value 10000 : exint - square (Value 100000); val it = Plus. Inf : exint 10/25/2020 IT 327 14
Type Constructors With Parameters Using Java/C++’s language, what are these all about? datatype 'a option = NONE | SOME of 'a; n n The parameters of a type constructor are type variables, which are used in the data constructors A polymorphic type SOME 1. 5 NONE "Hello" NONE SOME 123. 4 "world" string option real option 10/25/2020 SOME IT 327 15
- SOME val it 4; = SOME 4 : int option 1. 2; = SOME 1. 2 : real option "pig"; = SOME "pig" : string option is predefined - SOME; val it = fn : 'a -> 'a option n 10/25/2020 Type constuctor parameter comes before the type constructor name: datatype 'a option = NONE | SOME of 'a; 'a option, int option, just like 'a list, int list IT 327 16
Applications of option n n 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 option -optdiv 7 2; val it = SOME 3 : int option - optdiv 7 0; val it = NONE : int option 10/25/2020 IT 327 17
bunch type constructors datatype 'x bunch = One of 'x data constructors | Group of 'x list; n As usual, ML infers types: - One 1. 0; val it = One 1. 0 : real bunch - Group [true, false]; val it = Group [true, false] : bool bunch 10/25/2020 IT 327 18
Examples datatype 'x bunch = One of 'x | Group of 'x list; val a = One 3. 0; One 3. 0 : real bunch; val b = Group [1. 0, 2. 0, 5. 0]; Group [1. 0, 2. 0, 5. 0] : real bunch; val c = Group [1, 2, 5]; Group [1, 2, 5] : int bunch; val d = One 3; One 3 : int bunch; 10/25/2020 IT 327 19
Example: Polymorphism n ML can infer bunch types, but does not always have to resolve them, just as with list types - fun size (One _) = 1 = | size (Group x) = length x; val size = fn : 'a bunch -> int - size val it 10/25/2020 (One 1. 0); = 1 : int (Group [true, false]); = 2 : int IT 327 20
Example: No Polymorphism - fun sum (One x) = x = | sum (Group xlist) = foldr op + 0 xlist; val sum = fn : int bunch -> int - sum (One 5); use + to resolve val it = 5 : int - sum (Group [1, 2, 3]); val it = 6 : int n n We applied the + operator (through foldr) to the list elements So ML knows the parameter type must be int bunch 10/25/2020 IT 327 21
Recursively defined type constructors Definition of `a list 1) nil is a ‘a list 2) If e is ‘a and L is ‘a list, then e: : L is ‘a list type constructors datatype 'x data constructors 10/25/2020 = of 'x | IT 327 ; 22
Recursively Defined Type Constructors i. e. , using its own type constructor datatype intlist = INTNIL | INTCONS of int * intlist; - INTNIL; val it = INTNIL : intlist - INTCONS; val it = fn : int * intlist -> intlist - 10/25/2020 IT 327 23
datatype intlist = INTNIL | INTCONS of int * intlist; INTNIL INTCONS 1 INTNIL INTCONS 2 10/25/2020 3 INTCONS 2 INTCONS 1 INTNIL IT 327 INTCONS 1 INTNIL 24
Constructing intlist - INTNIL; val it = INTNIL : intlist - INTCONS (1, INTNIL); val it = INTCONS (1, INTNIL) : intlist - INTCONS (1, INTCONS(2, INTNIL)); val it = INTCONS (1, INTCONS (2, INTNIL)) : intlist INTNIL 10/25/2020 INTCONS 1 INTNIL 1 IT 327 INTCONS 2 INTNIL 25
fun list. Length nil = 0 | list. Length (_: : tail) = 1 + (list. Length tail); pattern matching An intlist Length Function: fun intlist. Length INTNIL = 0 | intlist. Length (INTCONS(_, tail)) = 1 + (int. List. Length tail); 10/25/2020 IT 327 26
Parametric List Type n datatype intlist = INTNIL | INTCONS of int * intlist; datatype 'element mylist = fixed NIL | CONS of 'element * 'element mylist; like ‘a list - CONS(1. 0, NIL); val it = CONS (1. 0, NIL) : real mylist - CONS(1, CONS(2, NIL)); val it = CONS (1, CONS (2, NIL)) : int mylist 10/25/2020 IT 327 27
list v. s. mylist - CONS(1. 0, NIL); val it = CONS (1. 0, NIL) : real mylist - CONS(1, CONS(2, NIL)); val it = CONS (1, CONS (2, NIL)) : int mylist - 1. 0: : nil; val it = [1. 0] : real list - 1: : 2: : nil; val it = [1, 2] : int list n mylist now works almost exactly like the predefined list type constructor 10/25/2020 IT 327 28
list v. s. mylist fun length nil = 0 | length (_: : tail) = 1 + length tail; fun my. Length NIL = 0 | my. Length (CONS(_, tail)) = 1 + my. Length(tail); fun addall nil = 0 | addall (a: : tail) = a + addall tail; fun addup NIL = 0 | addup (CONS(head, tail)) = head + addup tail; n add up a list you may use foldr… 10/25/2020 IT 327 29
Recall the foldr Function foldr f c [x 1, …, xn] computes: - foldr; val it = fn : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b 10/25/2020 IT 327 30
Define myfoldr for mylist So we can apply it to mylist x like : myfoldr (op +) 0 x; Or myfoldr (op ^) “” x; fun myfoldr _ c NIL = c | myfoldr f c (CONS(a, b)) = f(a, myfoldr f c b); 10/25/2020 IT 327 31
CONS is not an operator 'element = datatype 'a mylist = NIL | 'element * 'element mylist; CONS of 'a * 'a mylist; val ML = NIL; CONS (1, CONS(2, ML)); Now, it is infixr 5 CONS; 1 CONS 2 CONS NIL; val it = 1 CONS 2 CONS NIL : int mylist 10/25/2020 IT 327 32
Polymorphic Binary Tree datatype 'data tree = Empty | Node of 'data tree * 'data tree; Empty Node Empty 2 Empty Node Empty 10/25/2020 2 IT 327 Node Empty 33
Constructing 'a tree -val tree. Empty = Empty; val tree. Empty = Empty : 'a tree - val tree 2 = Node(Empty, 2, Empty); val tree 2 = Node (Empty, 2, Empty) : int tree - val tree 123 = Node(Empty, 1, Empty), = 2, = Node(Empty, 3, Empty)); 10/25/2020 IT 327 34
Increment All Elements fun inc. All Empty = Empty Pattern matching | inc. All (Node(x, y, z)) = Node(inc. All x, y+1, inc. All z); - inc. All tree 123; val it = Node (Empty, 2, Empty), 3, Node (Empty, 4, Empty)) : int tree 10/25/2020 IT 327 35
Add Up The Elements fun sum. All Empty = 0 | sum. All (Node(x, y, z)) = sum. All x + y + sum. All z; - sumall tree 123; val it = 6 : int 10/25/2020 IT 327 36
Convert To List (Polymorphic) fun list. All Empty = nil | list. All (Node(x, y, z)) = list. All x @ y : : list. All z; - list. All tree 123; val it = [1, 2, 3] : int list 10/25/2020 IT 327 37
Tree Search fun is. In. Tree x Empty = false | is. In. Tree x (Node(left, y, right)) = x=y orelse is. In. Tree x left orelse is. In. Tree x right; - is. In. Tree 4 tree 123; val it = false : bool - is. In. Tree 3 tree 123; val it = true : bool 10/25/2020 IT 327 38
That's all, folks! n What we have skipped: – – – – – 10/25/2020 records (like tuples with named fields) arrays, with elements that can be altered references, for values that can be altered exception handling structures: collections of datatypes, functions, etc. signatures: interfaces for structures functors: like functions that operate on structures, allowing type variables and other things to be instantiated across a whole structure predefined functions, types, etc. e. Xene: an ML library for applications that work in the X window system the Compilation Manager for building large ML projects IT 327 39
Other Functional Languages ML supports a function-oriented style of programming n Other popular functional languages: n 1. 2. 10/25/2020 Lisp Haskell IT 327 40
- Slides: 40