Functions, Patterns and Datatypes Creating New Functions Composition Currying Recursive Functions Patterns Programmer-defined Datatypes CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Composition and Currying in ML Combining two functions to create a new function by composition. h(x) = g(f(x)) ML provides the built in operator “o” Combining a function and one value to create a new function by currying. h(x) = f(a, x) ML does it implicitly. CSE 341 -- S. Tanimoto Functions, Patterns , and Types
CSE 341 -- S. Tanimoto Functions, Patterns , and Types Composition in ML fun f x = x+1; val f = fn : int -> int fun g y = 2*y; val g = fn : int -> int val h = g o f; val h = fn : int -> int h 5; val it = 12 CSE 341 -- S. Tanimoto Functions, Patterns , and Types
CSE 341 -- S. Tanimoto Functions, Patterns , and Types Currying in ML fun add (x,y) = x+y; val add = fn : int * int -> int add (7,2); val it = 9 fun plus x y = x+y; val plus = fn : int -> int -> int plus 7 2; val it = 9; val anotherWeek = plus 7; val anotherWeek = fn : int -> int anotherWeek 2; CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Recursive Functions in ML fun fact n = if n = 0 then 1 else n * fact (n-1); val fact = fn : int -> int fact 5; val it = 120 fact 100; uncaught exception overflow raised at <file stdin> CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Recursive Functions Using Patterns fun fact 0 = 1 | fact n = n * fact(n-1); val fact = fn : int -> int fact 5; val it = 120 CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Reversing a List: Using if fun rev lst = if lst = nil then nil else rev(tl(lst))@[hd(lst)]; val rev : fn ''a list -> ''a list rev [1, 2, 3, 4]; val it = [4, 3, 2, 1] : int list rev [“nice”, “feature”, “recursion”]; val it = [“recursion”, “feature”, “nice”] : string list rev [1.0, 2.0, 3.0]; Error: operator and operand don’t agree (equality type required) CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Reversing a List: Using Patterns fun rev2(nil) = nil | rev2(a::b) = rev2(b)@[a]; val rev2 : fn 'a list -> 'a list rev2 [1, 2, 3, 4]; val it = [4, 3, 2, 1] : int list rev2 [1.0, 1.2, 1.3]; val it = [1.3, 1.2, 1.0] : real list CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Programmer-Defined “Types” Use type to create a synonym or abbreviation for an existing type type piles = int list list; type piles = int list list val somepiles : piles = [[1,2,3],[4,5],[6,7]]; val sompiles = [[1,2,3],[4,5],[6,7]] : piles CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Programmer-Defined “Datatypes” Use datatype to create an entirely new type -- one which could not be expressed using only the basic types, tuples, and lists. datatype color = Red | Yellow | Green; datatype color Green | Red | Yellow val mycolor = Red; val mycolor = Red : color fun okToGo c = if c = Green then true else false; val okToGo fn : color -> bool okToGo(Red); val it = false : bool CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Datatypes with Constructors datatype tnode = L of int | I of int * tnode * tnode | NULL; (A tree node is either a Leaf containing an integer, an interior node containing an int and two tree nodes, or it’s NULL -- representing an empty tree.) CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Working with Datatypes (* tree.ml *) (* Create a binary tree, test whether an element occurs in the tree, and insert an element *) val mytree = I(50,I(25,L(10),L(40)),I(75,L(60),L(90))); fun member (i, NULL) = false | member (i, L(j)) = (i = j) | member (i, I(j, ls, rs)) = if i = j then true else if i < j then member (i, ls) else member (i, rs); CSE 341 -- S. Tanimoto Functions, Patterns , and Types
Working with Datatypes (Cont) fun insert (i, NULL) = L(i) | insert (i, L(j)) = if i = j then L(i) else if i < j then I(j,L(i),NULL) else I(j,NULL,L(i)) | insert (i, I(j, ls, rs)) = if i = j then I(i, ls, rs) else if i < j then I(j, insert(i,ls), rs) else I(j, ls, insert(i, rs)); CSE 341 -- S. Tanimoto Functions, Patterns , and Types