type synonyms CSC324 Functional Programming Typing, Exceptions in ML user-defined datatypes type synonyms

type synonyms We can give existing types new names. Syntax: type new type = ty CSC324 — Functional Programming Typing, Exceptions in ML new type bec...
Author: Amice Palmer
10 downloads 0 Views 175KB Size
type synonyms We can give existing types new names. Syntax: type new type = ty

CSC324 — Functional Programming Typing, Exceptions in ML

new type becomes an alias (a synonym) for the existing type ty. -type float = real; type float = real

Afsaneh Fazly1

-type count = int and average = real; type count = int type average = real

Winter 2013

-val f : float = 2.3; val f = 2.3: float -val i = 3 : count; val i = 3: count

1

with many thanks to Anya Tafliovich, Gerald Penn, Sheila McIlraith, Wael Aboelsaddat, Tony Bonner, Eric Joanis, Suzanne Stevenson. 1

2

type synonyms

user-defined datatypes

But notice float, real, and average are all of the same base type, i.e., real:

General Syntax: datatype new_type = Cons1 of type1 | Cons2 of type2 ... | ConsN of typeN

-val f : float = 2.3; val f = 2.3 : float -val a = f : average; val a = 2.3 : average

• Defines a new type called new type.

-val sum = a+f; val sum = 4.6 : average

• type1,...,typeN are previously defined types.

• Cons1,...,ConsN are constructors. They are used to create

a value of the type new type.

-val sum = f+a; val sum = 4.6 : float

• of type is omitted if a constructor does not need any

argument (such constructors are called constants).

3

4

enumerated types

enumerated types

All constructors are constants (no argument), e.g.:

How would you implement this in Python?

-datatype color = Red | Blue | Green; datatype color = Blue | Green | Red -val c = Red; val c = Red : color -fun colorStr Red = "red" | colorStr Blue = "blue" | colorStr Green= "green"; val colorStr = fn : color -> string -colorStr c; val it = "red" : string 6

5

enumerated types

variant types

How would you implement this in Python?

Create union of different types:

class Enum(set): def __getattr__(self, name): if name in self: return name raise AttributeError

datatype number =

color = Enum(["Red", "Blue", "Green"]) animal = Enum(["Dog", "Cat"]) print color.Green, animal.Dog Note: a class in Python (Java) essentially defines a new data type.

7

8

variant types

variant types

Create union of different types: datatype number = R of real | I of int;

datatype number = R of real | I of int;

val lst = [R 2.2, I 3, I 4, R 0.1];

val n1 = I 2;

Write a function sumInts that takes a number list and returns the sum of the integers:

val n2 = R 3.0; val lst = [R 2.2, I 3, I 4, R 0.1]; (* val lst = [R 2.2,I 3,I 4,R 0.1] : number list *) Note: a variant type is a non-specific type, e.g., number may hold a real or an integer.

10

9

variant types

recursive types Recursive types are good for defining dynamic data structures, e.g., a linked list:

datatype number = R of real | I of int; val lst = [R 2.2, I 3, I 4, R 0.1]; Write a function sumInts that takes a number list and returns the sum of the integers: fun sumInts [] = 0 | sumInts ((I x)::rest) = x + sumInts rest | sumInts ((R x)::rest) = sumInts rest; sumInts : number list -> int; sumInts lst; (* val it = 7 : int *)

11

12

recursive types

recursive types

Recursive types are good for defining dynamic data structures, e.g., a linked list:

Recursive types are good for defining dynamic data structures, e.g., a linked list:

datatype llist = Nil | Node of int * llist;

datatype llist = Nil | Node of int * llist; (* constructing instances of the linked list *) val x = Nil; val y = Node(5,Nil); val z = Node(3, Node(2, Node(1,Nil)));

13

recursive types in Python

14

recursive types

class LinkedList: def __init__(): ’’’creates an initial linked list’’’ self.first = LinkedList.__Node()

datatype llist = Nil | Node of int * llist; val z = Node(3, Node(2, Node(1,Nil)));

def addNode(element): ...

Write a function len that takes a llist and returns its length.

class __Node: ’’’private node obj: element + pointer to next Node’’’ def __init__(self, element=None): self.element = element self.next = None def hasNext(self): ... def getNext(self): ... def setNext(self, nextNode): ... ... 15

16

recursive types

recursive types What about a polymorphic linked list?

datatype llist = Nil | Node of int * llist; val z = Node(3, Node(2, Node(1,Nil))); Write a function len that takes a llist and returns its length. (* length of a linked list *) fun len Nil = 0 | len (Node (_,xs)) = 1 + len xs; len : llist -> int len z; val it = 3 : int

18

17

recursive types

recursive types

What about a polymorphic linked list?

What about a polymorphic linked list?

• Use a type variable.

• Use a type variable.

Remember type variables: ’a ⇒ any type ’’a ⇒ any type for which equality is defined

Remember type variables: ’a ⇒ any type ’’a ⇒ any type for which equality is defined

datatype ’a llist = Nil | Node of ’a * (’a llist);

18

19

recursive types

recursive types

A polymorphic linked list: datatype ’a llist = Nil | Node of ’a * (’a llist);

datatype ’a llist = Nil | Node of ’a * (’a llist); val y = Node(5,Nil);

fun len Nil = 0 | len (Node (_,xs)) = 1 + len xs; len : ’a llist -> int

(* int llist *)

val z = Node("A", Node("B",Nil));

(* string llist *)

len y; (* val it = 1 : int *) len z; (* val it = 2 : int *)

21

20

recursive types

recursive types

Example: a polymorphic binary tree.

Example: a polymorphic binary tree. datatype ’a tree = Leaf of ’a | Node of ’a * ’a tree * ’a tree;

22

23

recursive types

recursive types

Example: a polymorphic binary tree.

Example: a polymorphic binary tree.

datatype ’a tree = Leaf of ’a | Node of ’a * ’a tree * ’a tree;

datatype ’a tree = Leaf of ’a | Node of ’a * ’a tree * ’a tree;

Function for summing-up all values in an int tree:

Function for summing-up all values in an int tree: fun sumT (Leaf x) = x | sumT (Node(x,ltree,rtree)) = x + sumT(ltree) + sumT(rtree);

25

24

recursive types

recursive types

Example: Tree representation of simple mathematical expressions.

datatype math_tree = Leaf of int | Unary of (int -> int) * math_tree | Binary of (int * int -> int) * math_tree * math_tree

(|-3| + 2) + ((-1) + 4) * 7)

add add

mult

abs neg 3

2 neg

add

7 4

1

What is the datatype we need? 26

27

recursive types

recursive types The tree in the figure:

datatype math_tree = Leaf of int | Unary of (int -> int) * math_tree | Binary of (int * int -> int) * math_tree * math_tree

val t = Binary(op +, Binary(op +, Unary((fn x => if x > 0 then x else ~x), Unary (op ~, Leaf 3)), Leaf 2), Binary(op *, Binary(op +, Unary(op ~, Leaf 1), Leaf 4), Leaf 7))

Instances of type math tree: Leaf 3; Unary(op ~, Leaf 3); Binary(op +, Leaf 4, Unary(op ~, Leaf 3));

28

29

recursive types

recursive types

Define a function eval: math tree -> int that returns the result of evaluatng a math tree:

Define a function eval: math tree -> int that returns the result of evaluatng a math tree: fun eval (Leaf n) = n | eval (Unary (f,t)) = f (eval t) | eval (Binary (f,l,r)) = f (eval l,eval r); eval : math_tree -> int - eval t; val it = 26 : int

30

31

recursive types in Python/Java

recursive types in Python/Java

How would you define the datatype math tree and the function eval in Python or Java?

How would you define the datatype math tree and the function eval in Python or Java?

What differences do you see between ML and Python/Java?

32

32

mutual recursion in ML

mutual recursion in ML

Let’s mimic the Scheme definitions of even and odd:

Use the keyword and.

fun even 0 = true | even x = odd (x - 1);

fun | and |

fun odd 0 = false | odd x = even (x - 1); Error:

unbound variable or constructor:

even 0 = true even x = odd (x - 1) odd 0 = false odd x = even (x - 1);

even : int -> bool; odd : int -> bool

odd

even 42; (* val it = true : bool *) odd 42; (* val it = false : bool *)

33

34

mutually recursive types

mutually recursive types

Example: a binary tree with labeled branches:

Example: a binary tree with labeled branches:

6

1

7

2

8

7

2

3

4

6

1

8

3

4

5

5

datatype ’a tree = Empty | Node of ’a branch * ’a branch and ’a branch = Branch of ’a * ’a tree; 36

35

mutually recursive types

mutually recursive types The tree in the figure:

datatype ’a tree = Empty | Node of ’a branch * ’a branch and ’a branch = Branch of ’a * ’a tree;

val lt = Node(Branch(1, Node(Branch(2, Empty), Branch(3, Node(Branch(4, Empty), Branch(5, Empty))))), Branch(6, Node(Branch(7, Empty), Branch(8, Empty))));

Instances of tree: Empty; Node(Branch(7,Empty), Branch(8,Empty)); Node(Branch(1,Empty), Branch(6, Node(Branch(7,Empty), Branch(8,Empty)))); 37

38

mutually recursive types

mutually recursive types

datatype ’a tree = Empty | Node of ’a branch * ’a branch and ’a branch = Branch of ’a * ’a tree

datatype ’a tree = Empty | Node of ’a branch * ’a branch and ’a branch = Branch of ’a * ’a tree

Define listTree that returns the list of branch labels, in order:

Define listTree that returns the list of branch labels, in order: fun listTree Empty = [] | listTree (Node (l,r)) = (listBranch l) @ (listBranch r) and listBranch (Branch (b,t)) = b :: (listTree t); listTree : ’a tree -> ’a list; listBranch : ’a branch -> ’a list listTree t; (* val it = [1,2,3,4,5,6,7,8] : int list *)

39

recursive types 1. A powerful tool for constructing new types. 2. The structure of the datatype suggests the structure of the recursive function on the datatype ⇒ structural recursion.

41

40

Suggest Documents