13.07.2015 Views

Basic types, Lists, Trees, Higher-order functions

Basic types, Lists, Trees, Higher-order functions

Basic types, Lists, Trees, Higher-order functions

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Basic</strong> Types: IntegersA data type comprises• a set of values and• a collection of operationsIntegersType name : intValues : ˜27, 0, 1024Operations: (A few selected)Operator Type Precedence Association˜ int -> int Highest* div mod int * int -> int 7 Left+ - int * int -> int 6 Left= < bool 4 LeftSee also the library Intc○Michael R. Hansen, Spring 2005 – p.2/59


RealsType name : realValues : ˜27.0, 0.0, 1024.71717, 23.4E˜11Operations: (A few selected)Operator Type Precedence Associationabs real -> real Highest* / real*real -> real 7 Left+ - real*real -> real 6 Left= < bool 4 LeftSee also the libraries Real and Mathc○Michael R. Hansen, Spring 2005 – p.3/59


RealsType name : realValues : ˜27.0, 0.0, 1024.71717, 23.4E˜11Operations: (A few selected)Operator Type Precedence Associationabs real -> real Highest* / real*real -> real 7 Left+ - real*real -> real 6 Left= < bool 4 LeftSee also the libraries Real and MathSome built-in operators are overloaded. *:Default is intreal*real -> realint * int -> intc○Michael R. Hansen, Spring 2005 – p.3/59


Overloaded Operators and Type inferenceA squaring function on integers:DeclarationTypefun square x = x * x int -> int Defaultc○Michael R. Hansen, Spring 2005 – p.4/59


Overloaded Operators and Type inferenceA squaring function on integers:DeclarationTypefun square x = x * x int -> int DefaultA squaring function on reals: square:real -> realDeclarationc○Michael R. Hansen, Spring 2005 – p.4/59


Overloaded Operators and Type inferenceA squaring function on integers:DeclarationTypefun square x = x * x int -> int DefaultA squaring function on reals: square:Declarationfun square(x:real) = x * xreal -> realType the argumentc○Michael R. Hansen, Spring 2005 – p.4/59


Overloaded Operators and Type inferenceA squaring function on integers:DeclarationTypefun square x = x * x int -> int DefaultA squaring function on reals: square:real -> realDeclarationfun square x:real = x * xType the resultc○Michael R. Hansen, Spring 2005 – p.4/59


Overloaded Operators and Type inferenceA squaring function on integers:DeclarationTypefun square x = x * x int -> int DefaultA squaring function on reals: square:real -> realDeclarationfun square x = x * x: real Type expression for the resultc○Michael R. Hansen, Spring 2005 – p.4/59


Overloaded Operators and Type inferenceA squaring function on integers:DeclarationTypefun square x = x * x int -> int DefaultA squaring function on reals: square:real -> realDeclarationfun square x = x:real * xType a variablec○Michael R. Hansen, Spring 2005 – p.4/59


Overloaded Operators and Type inferenceA squaring function on integers:DeclarationTypefun square x = x * x int -> int DefaultA squaring function on reals: square:real -> realDeclarationfun square x = x:real * xType a variableChoose any mixture of these possibilitiesc○Michael R. Hansen, Spring 2005 – p.4/59


CharactersType name charValues #"a", #" ", #"\"" (escape sequence for ")Operator Typeord char -> int ascii code of characterchr int -> char character for ascii code= < bool comparisons by ascii codesExamples- ord #"a";> val it = 97 : int- ord #"A";> val it = 65 : int- #"a" < #"A";> val it = false : bool;- chr 88;> val it = #"X" : charc○Michael R. Hansen, Spring 2005 – p.5/59


StringsType name stringValues "abcd", " ", "", "123\"321" (escape sequence for ")Operator Typesize string -> int length of stringˆ string*string -> string concatenation= < bool comparisonsInt.toString int -> string conversionsExamples- "auto" < "car";> val it = true : bool- "abc"ˆ"de";> val it = "abcde": string- size("abc"ˆ"def");> val it = 6 : int- Int.toString(6+18);> val it = "24" : stringc○Michael R. Hansen, Spring 2005 – p.6/59


BooleansType name boolValues false, trueOperatorTypenot bool -> bool negationnot true = falsenot false = trueExpressionse 1 andalso e 2 “conjunction e 1 ∧ e 2 ”e 1 orelse e 2 “disjunction e 1 ∨ e 2 ”— are lazily evaluated, e.g.1


TuplesAn <strong>order</strong>ed collection of n values (v 1 , v 2 , . . . , v n ) is called an n-tupleExamples- ();> val it = () : unit- (3, false);> val it = (3, false) : int * bool- (1, 2, ("ab",true));> val it = (1, 2, ("ab", true)) : ?0-tuple2-tuples (pairs)3-tuples (triples)Selection Operation: #i(v 1 , v 2 , . . . , v n ) = v i . #2(1,2,3) = 2Equality defined componentwise- (1, 2.0, true) = (2-1, 2.0*1.0, 1 val it = true : boolprovided = is defined on componentsc○Michael R. Hansen, Spring 2005 – p.8/59


Tuple patternsExtract components of tuples- val ((x,_),(_,y,_)) = ((1,true),("a","b",false));> val x = 1 : intval y = "b" : stringPattern matching yields bindingsRestriction- val (x,x) = (1,1);! Toplevel input:! val (x,x) = (1,1);! ˆ! identifier is bound twice in a patternc○Michael R. Hansen, Spring 2005 – p.9/59


Infix <strong>functions</strong>Directives: infix d f and infixr d f. d is the precedence of fExample: exclusive-orinfix 0 xor(* or just infix xor-- lowest precedence *)fun false xor true = true| true xor false = true| _ xor _ = falsetype ?- 1 < 2+3 xor 2.0 / 3.0 > 1.0;> val it = true : boolInfix status can be removed by nonfix xor- xor(1 < 2+3, 2.0 / 3.0 > 1.0);> val it = true : boolc○Michael R. Hansen, Spring 2005 – p.10/59


Let expressions — let dec in e endBindings obtained from dec are valid only in eExample: Solve ax 2 + bx + c = 0type equation = real * real * realtype solution = real * realexception Solve; (* declares an exception *)fun solve(a,b,c) =let val d = b*b-4.0*a*cin if d < 0.0 orelse a = 0.0 then raise Solveelse ((˜b+Math.sqrt d)/(2.0*a),(˜b-Math.sqrt d)/(2.0*a))end;The type of solve is equation -> solutiond is declared once and used 3 timesreadability, efficiencyc○Michael R. Hansen, Spring 2005 – p.11/59


Local declarations — local dec 2 in dec 2 endBindings obtained from dec 1 are valid only in dec 2localfun disc(a,b,c) = b*b - 4.0*a*cinexception Solve;fun hasTwoSolutions(a,b,c) = disc(a,b,c)>0.0andalso a0.0;fun solve(a,b,c) =let val d = disc(a,b,c)in if d < 0.0 orelse a = 0.0 then raise Solveelse ((˜b+Math.sqrt d)/(2.0*a),(˜b-Math.sqrt d)/(2.0*a))endend;c○Michael R. Hansen, Spring 2005 – p.12/59


<strong>Lists</strong>: Overview• values and constructors• recursions following the structure of lists• useful built-in <strong>functions</strong>• polymorphic <strong>types</strong>, values and <strong>functions</strong>c○Michael R. Hansen, Spring 2005 – p.13/59


<strong>Lists</strong>A list is a finite sequence of elements having the same type:[v 1 , . . . , v n ] ([ ] is called the empty list)c○Michael R. Hansen, Spring 2005 – p.14/59


<strong>Lists</strong>A list is a finite sequence of elements having the same type:[v 1 , . . . , v n ] ([ ] is called the empty list)- [2,3,6];> val it = [2, 3, 6] : int listc○Michael R. Hansen, Spring 2005 – p.14/59


<strong>Lists</strong>A list is a finite sequence of elements having the same type:[v 1 , . . . , v n ] ([ ] is called the empty list)- ["a", "ab", "abc", ""];> val it = ["a", "ab", "abc", ""] : string listc○Michael R. Hansen, Spring 2005 – p.14/59


<strong>Lists</strong>A list is a finite sequence of elements having the same type:[v 1 , . . . , v n ] ([ ] is called the empty list)- [Math.sin, Math.cos];> val it = [fn, fn] : (real -> real) listc○Michael R. Hansen, Spring 2005 – p.14/59


<strong>Lists</strong>A list is a finite sequence of elements having the same type:[v 1 , . . . , v n ] ([ ] is called the empty list)- [(1,true), (3,true)];> val it = [(1, true),(3, true)]: (int*bool)listc○Michael R. Hansen, Spring 2005 – p.14/59


<strong>Lists</strong>A list is a finite sequence of elements having the same type:[v 1 , . . . , v n ] ([ ] is called the empty list)- [[],[1],[1,2]];> val it = [[], [1], [1, 2]] : int list listc○Michael R. Hansen, Spring 2005 – p.14/59


The type constructor: listIf τ is a type, so is τ listExamples:• int list• (string * int) list• ((int -> string) list ) listlist has higher precedence than * and ->int * real list -> bool listmeans(int * (real list)) -> (bool list)c○Michael R. Hansen, Spring 2005 – p.15/59


<strong>Trees</strong> for listsA non-empty list [x 1 , x 2 , . . . , x n ], n ≥ 1, consists of• a head x 1 and• a tail [x 2 , . . . , x n ]c○Michael R. Hansen, Spring 2005 – p.16/59


<strong>Trees</strong> for listsA non-empty list [x 1 , x 2 , . . . , x n ], n ≥ 1, consists of• a head x 1 and• a tail [x 2 , . . . , x n ]::❅ ❅❅2 ::❅ ❅❅3 ::❅ ❅❅2 nilGraph for [2,3,2]::❅ ❅❅2 nilGraph for [2]c○Michael R. Hansen, Spring 2005 – p.16/59


List constructors: [], nil and ::<strong>Lists</strong> are generated as follows:• the empty list is a list, designated [] or nil• if x is an element and xs is a list,then so is x :: xs(type consistency):: associate to the right, i.e. x 1 ::x 2 ::xsc○Michael R. Hansen, Spring 2005 – p.17/59


List constructors: [], nil and ::<strong>Lists</strong> are generated as follows:• the empty list is a list, designated [] or nil• if x is an element and xs is a list,then so is x :: xs(type consistency):: associate to the right, i.e. x 1 ::x 2 ::xs means x 1 ::(x 2 ::xs)c○Michael R. Hansen, Spring 2005 – p.17/59


List constructors: [], nil and ::<strong>Lists</strong> are generated as follows:• the empty list is a list, designated [] or nil• if x is an element and xs is a list,then so is x :: xs(type consistency):: associate to the right, i.e. x 1 ::x 2 ::xs means x 1 ::(x 2 ::xs)::❅ ❅❅x 1 ::x 2❅ ❅❅xsGraph for x 1 ::x 2 ::xsc○Michael R. Hansen, Spring 2005 – p.17/59


Recursion on lists – a simple examplen∑suml [x 1 ,x 2 , . . . ,x n ] = x i = x 1 + x 2 + · · · + x n = x 1 +i=1n∑i=2x iConstructors are used in list patternsfun suml [] = 0| suml( x::xs) = x + suml xs> val suml = fn : int list -> intsuml [1,2] 1 + suml [2] (x ↦→ 1 and xs ↦→ [2]) 1 + (2 + suml []) (x ↦→ 2 and xs ↦→ []) 1 + (2 + 0) (the pattern [] matches the value []) 1 + 2 3Recursion follows the structure of listsc○Michael R. Hansen, Spring 2005 – p.18/59


AppendThe infix operator @ (called ‘append’) joins two lists:Properties[x 1 ,x 2 , . . . ,x m ] @ [y 1 ,y 2 , . . . ,y n ]= [x 1 ,x 2 , . . . ,x m ,y 1 ,y 2 , . . . ,y n ][] @ ys = ys[x 1 ,x 2 , . . . ,x m ] @ ys = x 1 ::([x 2 , . . . ,x m ] @ ys)Declarationinfixr 5 @ (* right associativefun [] @ ys = ys| (x::xs) @ ys = x::(xs @ ys);c○Michael R. Hansen, Spring 2005 – p.19/59


Append: evaluationinfixr 5 @ (* right associative *)fun [] @ ys = ys| (x::xs) @ ys = x::(xs @ ys);Evaluation[1,2] @ [3,4] 1::([2] @ [3,4]) (x ↦→ 1, xs ↦→ [2], ys ↦→ [3, 4]) 1::(2::([] @ [3,4])) (x ↦→ 2, xs ↦→ [ ], ys ↦→ [3, 4]) 1::(2::[3,4]) (ys ↦→ [3, 4]) 1::[2,3,4] [1,2,3,4]c○Michael R. Hansen, Spring 2005 – p.20/59


Append: polymorphic type> infixr 5 @> val @ = fn : ’a list * ’a list -> ’a list• ’a is a type variable• The type of @ is polymorphic — it has many forms’a = int: Appending integer lists[1,2] @ [3,4];val it = [1,2,3,4] : int list’a = int list: Appending lists of integer list[[1],[2,3]] @ [[4]];val it = [[1],[2,3],[4]] : int list list@ is a built-in functionc○Michael R. Hansen, Spring 2005 – p.21/59


Reverse rev [x 1 , x 2 , . . . , x n ] = [x n , . . . , x 2 , x 1 ]fun naive_rev [] = []| naive_rev(x::xs) = naive_rev xs @ [x];val naive_rev = fn : ’a list -> ’a listnaive_rev[1,2,3] naive_rev[2,3] @ [1] (naive_rev[3] @ [2]) @ [1] ((naive_rev[] @ [3]) @ [2]) @ [1] (([] @ [3]) @ [2]) @ [1] ([3] @ [2]) @ [1] (3::([] @ [2])) @ [1] · · · [3,2,1]efficient version is built-in (see Ch. 17)c○Michael R. Hansen, Spring 2005 – p.22/59


Membership — equality <strong>types</strong>Declarationinfix memberx member [y 1 ,y 2 , . . . ,y n ]= (x = y 1 ) ∨ (x = y 2 ) ∨ · · · ∨ (x = y n )= (x = y 1 ) ∨ (x member [y 2 , . . . ,y n ])fun x member [] = false| x member (y::ys) = x=y orelse x member ys;infix 0 memberval member = fn : ’’a * ’’a list -> bool• ’’a is an equality type variable no <strong>functions</strong>• (1,true) member [(2,true), (1,false)] false• [1,2,3] member [[1], [], [1,2,3]] ?c○Michael R. Hansen, Spring 2005 – p.23/59


Value polymorphism• e is a value expression if no further evaluation is needed- (5,[]); (* val it = (5,[]); *)> val ’a it = (5, []) : int * ’a list- rev []; (* non-value expression *)! Warning: Value polymorphism:! Free type variable(s) at top level in value id. it• A type is monomorphic is it contains no type variables,otherwise it is polymorphicSML resticts the use of polymorphic <strong>types</strong> as follows: see Ch. 18• all monomorphic expressions are OK• all value expressions are OK• at top-level, polymorphic non-value expressions are forbiddenc○Michael R. Hansen, Spring 2005 – p.24/59


Examples• remove(x, ys) : removes all occurrences of x in the list ys• prefix(xs, ys) : the list xs is a prefix of the list ys (ex. 5.10)• sum(p, xs) : the sum of all elements in xs satisfying thepredicate p: int -> bool (ex. 5.15)• From list of pairs to pair of lists:unzip [(x 1 , y 1 ), (x 2 , y 2 ), . . . , (x n , y n )]= ([x 1 , x 2 , . . . , x n ], [y 1 y 2 , . . . , y n ])Many <strong>functions</strong> on lists are predefined, e.g. @, rev, length, andalso the SML basis library contains <strong>functions</strong> on lists, e.g. unzip.See for example List, ListPairc○Michael R. Hansen, Spring 2005 – p.25/59


Overview• Disjoint Sets• The datatype – simple version• case expressionsc○Michael R. Hansen, Spring 2005 – p.26/59


Disjoint Sets: An ExampleA shape is either a circle, a square, or a triangle• the union of three disjoint setsA datatype declaration for shapes:datatype shape = Circle of real| Square of real| Triangle of real*real*real;Answer from the SML system:> datatype shape> con Circle = fn : real -> shape> con Square = fn : real -> shape> con Triangle = fn : real * real * real -> shapec○Michael R. Hansen, Spring 2005 – p.27/59


Constructors of a datatypeThe tags Circle, Square and Triangle are constructors ofvalues of type shape- Circle 2.0;> val it = Circle 2.0 : shape- Triangle(1.0, 2.0, 3.0);> val it = Triangle(1.0, 2.0, 3.0) : shape- Square 4.0;> val it = Square 4.0 : shapeEquality on shapes is defined provided . . .- Triangle(1.0, 2.0, 3.0) = Square 2.0;> val it = false : boolc○Michael R. Hansen, Spring 2005 – p.28/59


Constructors in Patternsfun area(Circle r) = Math.pi * r * r| area(Square a) = a * a| area(Triangle(a,b,c)) =let val d = (a + b + c)/2.0in Math.sqrt(d*(d-a)*(d-b)*(d-c))end;> val area = fn : shape -> real• a constructor only matches itselfarea (Circle 1.2) (Math.pi * r * r, [r ↦→ 1.2]) . . .c○Michael R. Hansen, Spring 2005 – p.29/59


The case-expressionForm:case exp ofpat 1 => e 1| pat 2 => e 2. . .| pat k => e kExample:fun area s =case s of(Circle r) => Math.pi * r * r| (Square a) => a*a| (Triangle(a,b,c)) =>let val d = (a + b + c)/2.0in Math.sqrt(d*(d-a)*(d-b)*(d-c))end;c○Michael R. Hansen, Spring 2005 – p.30/59


Enumeration <strong>types</strong> – the <strong>order</strong> typedatatype <strong>order</strong> = LESS | EQUAL | GREATER;Predefined ‘compare’ <strong>functions</strong>, e.g.⎧⎪⎨ LESS if x < yInt.compare(x, y) = EQUAL if x = y⎪⎩GREATER if x > yExample:fun countLEG [] = (0,0,0)| countLEG(x::rest) =let val (y1,y2,y3) = countLEG rest incase Int.compare(x,0) ofLESS => (y1+1,y2 ,y3 )| EQUAL => (y1 ,y2+1,y3 )| GREATER => (y1 ,y2 ,y3+1)end;c○Michael R. Hansen, Spring 2005 – p.31/59


The option typedatatype ’a option = NONE | SOME of ’a;Examplefun smallest [] = NONE| smallest(x::xs) =case smallest xs ofNONE => SOME x| SOME y => if x< y then SOME x else SOME y;> val smallest = fn : int list -> int option- smallest [2, ˜3, 6];> val it = SOME ˜3 : int optionc○Michael R. Hansen, Spring 2005 – p.32/59


smallest — continuedThe predefined function valOf:exception Option;fun valOf(SOME x) = x| valOf NONE = raise Option;> val ’a valOf = fn : ’a option -> ’a- 3 + valOf(smallest [1,2,9]);> val it = 4 : intc○Michael R. Hansen, Spring 2005 – p.33/59


OverviewFinite <strong>Trees</strong>• Algebraic Data<strong>types</strong>.• Recursions following the structure of trees.c○Michael R. Hansen, Spring 2005 – p.34/59


<strong>Trees</strong>A finite tree is a value which may contain a subcomponent of thesame type.Example: A binary search treeBrBr✦❛ ❛❛❛❛❛✦ ✦✦✦✦ ✦❛Br✧❜ ✧❜ ✧ ❜❜ ✧ ❜❜✧✧✧❜✧❜Br 7 Lf Br 21 Br✜❭ ✪❭ ✪❭ ✜ ❭❭ ✪ ❭❭ ✪ ❭❭✜✪✪Lf 2 Lf9Lf 13 Lf Lf 25 LfCondition: for every node containing the value x: every value in theleft subtree is smaller then x, and every value in the right subtree isgreater than x.c○Michael R. Hansen, Spring 2005 – p.35/59


Binary <strong>Trees</strong>A recursive datatype is used to represent values with are trees.datatype tree = Lf | Br of tree*int*tree;> datatype tree> con Lf = Lf : tree> con Br = fn : tree * int * tree -> treec○Michael R. Hansen, Spring 2005 – p.36/59


Binary <strong>Trees</strong>A recursive datatype is used to represent values with are trees.datatype tree = Lf | Br of tree*int*tree;> datatype tree> con Lf = Lf : tree> con Br = fn : tree * int * tree -> treeThe two parts in the declaration are rules for generating trees:• Lf is a tree• if t 1 , t 2 are trees, n is an integer, then Br(t 1 , n, t 2 ) is a tree.c○Michael R. Hansen, Spring 2005 – p.36/59


Binary <strong>Trees</strong>A recursive datatype is used to represent values with are trees.datatype tree = Lf | Br of tree*int*tree;> datatype tree> con Lf = Lf : tree> con Br = fn : tree * int * tree -> treeThe two parts in the declaration are rules for generating trees:• Lf is a tree• if t 1 , t 2 are trees, n is an integer, then Br(t 1 , n, t 2 ) is a tree.The tree from the previous slide is denoted by:Br(Br(Br(Lf,2,Lf),7,Lf),9,Br(Br(Lf,13,Lf),21,Br(Lf,25,Lf)))c○Michael R. Hansen, Spring 2005 – p.36/59


Binary search trees: InsertionRecursion on the structure of trees:• Constructors Lf and Br are used in patternsfun insert(i, Lf)= Br(Lf,i,Lf)| insert(i, tr as Br(t1,j,t2)) =case Int.compare(i,j) ofEQUAL => tr| LESS => Br(insert(i,t1),j,t2)| GREATER => Br(t1,j,insert(i,t2))• The search tree condition is an invariant for insertExample:- val t1 = Br(Lf, 3, Br(Lf, 5, Lf));- val t2 = insert(4, t1);> val t2 = Br(Lf, 3, Br(Br(Lf, 4, Lf), 5, Lf)) : treec○Michael R. Hansen, Spring 2005 – p.37/59


Binary search trees: member and toListfun member(i, Lf)= false| member(i, Br(t1,j,t2)) =case Int.compare(i,j) ofEQUAL => true| LESS => member(i,t1)| GREATER => member(i,t2)> val member = fn : int * tree -> boolIn-<strong>order</strong> traversalfun toList Lf = []| toList(Br(t1,j,t2)) = toList t1 @ [j] @ toList t2;> val toList = fn : tree -> int listgives a sorted list- toList(Br(Br(Lf,1,Lf), 3, Br(Br(Lf,4,Lf), 5, Lf)));> val it = [1, 3, 4, 5] : int listc○Michael R. Hansen, Spring 2005 – p.38/59


Deletions in search treesDelete minimal element in a search tree: tree -> int * treefun delMin(Br(Lf,i,t2)) = (i,t2)| delMin(Br(t1,i,t2)) = let val (m,t1’) = delMin t1in (m, Br(t1’,i,t2)) endDelete element in a search tree: tree * int -> treefun delete(Lf,_)= Lf| delete(Br(t1,i,t2),j) =case Int.compare(i,j) ofLESS => Br(t1,i,delete(t2,j))| GREATER => Br(delete(t1,j),i,t2)| EQUAL =>(case (t1,t2) of(Lf,_) => t2| (_,Lf) => t1| _ => let val (m,t2’) = delMin t2in Br(t1,m,t2’) end)c○Michael R. Hansen, Spring 2005 – p.39/59


Expression <strong>Trees</strong>infix 6 ++ --;infix 7 ** //;datatype fexpr =Const of real| X| ++ of fexpr * fexpr | -- of fexpr * fexpr| ** of fexpr * fexpr | // of fexpr * fexpr> datatype fexprcon ** : fexpr * fexpr -> fexprcon ++ : fexpr * fexpr -> fexprcon -- : fexpr * fexpr -> fexprcon // : fexpr * fexpr -> fexprcon X : fexprcon Const : real -> fexprc○Michael R. Hansen, Spring 2005 – p.40/59


Expressions: Computation of valuescomp : fexpr * real -> realfun comp(Const r,_) = r| comp(X,y) = y| comp(fe1 ++ fe2,y) = comp(fe1,y) + comp(fe2,y)| comp(fe1 -- fe2,y) = comp(fe1,y) - comp(fe2,y)| comp(fe1 ** fe2,y) = comp(fe1,y) * comp(fe2,y)| comp(fe1 // fe2,y) = comp(fe1,y) / comp(fe2,y)Example:comp(X ** (Const 2.0 ++ X), 4.0);> val it = 24.0 : realc○Michael R. Hansen, Spring 2005 – p.41/59


OverviewContents• <strong>Higher</strong>-<strong>order</strong> <strong>functions</strong>• Anonymous <strong>functions</strong>• <strong>Higher</strong>-<strong>order</strong> list <strong>functions</strong> (in the library)• map• exists, all, filter• foldl, foldr• Many recursive declarations follows the same schema.— Succinct declarations using higher-<strong>order</strong> <strong>functions</strong>.• Parameterization of program modulesc○Michael R. Hansen, Spring 2005 – p.42/59


<strong>Higher</strong>-<strong>order</strong> <strong>functions</strong>A function f : τ 1 → τ 2 is a higher-<strong>order</strong> function, if a function typeτ → τ ′ occurs in either τ 1 or τ 2 or both.Functions are first class citizensc○Michael R. Hansen, Spring 2005 – p.43/59


<strong>Higher</strong>-<strong>order</strong> <strong>functions</strong>A function f : τ 1 → τ 2 is a higher-<strong>order</strong> function, if a function typeτ → τ ′ occurs in either τ 1 or τ 2 or both.fun f x = let fun g y = x+y in g end;> val f = fn : int -> int -> int- f 2;> val it = fn : int -> int- it 3;> val it = 5 : intFunctions are first class citizensc○Michael R. Hansen, Spring 2005 – p.43/59


Anonymous <strong>functions</strong>Expressions denoting <strong>functions</strong> can be written using fn expressions:fn pat 1 => e 1 | pat 2 => e 2 | · · · | pat n => e nYields the value obtained by evaluation of the expression:let fun f x = case x ofpat 1 => e 1 | pat 2 => e 2 | · · · | pat n => e nin f endExamples:fn n => 2 * n;fn 0 => false | _ => true;fn r => Math.pi * r * r;c○Michael R. Hansen, Spring 2005 – p.44/59


Declarations having the same structurefun posList [] = []| posList (x::xs) = (x > 0)::posList xs;val posList = fn : int list -> bool listposList [4, ˜5, 6];> val it = [true,false,true] : bool listApplies the function fn x => x > 0 to each element in a listfun addElems [] = []| addElems ((x,y)::zs) = (x + y)::addElems zs;> val addElems = fn : (int * int) list -> int listaddElems [(1,2),(3,4)];> val it = [3, 7] : int listApplies the sum function op+ to each pair of integers in a listc○Michael R. Hansen, Spring 2005 – p.45/59


The function: mapApplies a function to each element in a listmap f [v 1 , v 2 , . . . , v n ] = [f(v 1 ), f(v 2 ), . . . , f(v n )]DeclarationLibrary functionfun map f = fn [] => []| (x::xs) => f x :: map f xs;> val map = fn : (’a -> ’b) -> ’a list -> ’b listSuccinct declarations can be achieved using map, e.g.val posList = map (fn x => x > 0);> val posList = fn : int list -> bool listval addElems = map op+- val addElems = fn : (int * int) list -> int listc○Michael R. Hansen, Spring 2005 – p.46/59


Declaration of higher-<strong>order</strong> <strong>functions</strong>Commonly used formfun map f [] = []| map f (x::xs) = f x :: map f xs;> val map = fn : (’a -> ’b) -> ’a list -> ’b listGeneral formfun f pat 11 pat 12 . . . pat 1n = e 1| f pat 21 pat 22 . . . pat 2n = e 2| . . .| f pat k1 pat k2 . . . pat kn = e kc○Michael R. Hansen, Spring 2005 – p.47/59


ExerciseDeclare a functiong [x 1 , . . . , x n ] = [x 2 1 + 1, . . . , x 2 n + 1]Remembermap f [v 1 , v 2 , . . . , v n ] = [f(v 1 ), f(v 2 ), . . . , f(v n )]c○Michael R. Hansen, Spring 2005 – p.48/59


<strong>Higher</strong>-<strong>order</strong> list <strong>functions</strong>: existsexists p xs ={truefalseif p(x) = true for some x in xsotherwiseDeclarationLibrary functionfun exists p [] = false| exists p (x::xs) = p x orelse exists p xs;> val exists = fn: (’a -> bool) -> ’a list -> boolExampleexists (fn x => x>=2) [1,3,1,4];> val it = true : boolc○Michael R. Hansen, Spring 2005 – p.49/59


ExerciseDeclare member function using exists.infix member;fun x member ys = exists ????? ;> val member = fn : ’’a * ’’a list -> boolRememberexists p xs ={truefalseif p(x) = true for some x in xsotherwisec○Michael R. Hansen, Spring 2005 – p.50/59


<strong>Higher</strong>-<strong>order</strong> list <strong>functions</strong>: all{all p xs =truefalseif p(x) = true, for all elements x in xsotherwiseDeclarationLibrary functionfun all p [] = true| all p (x::xs) = p x andalso all p xs;> val all = fn: (’a -> bool) -> ’a list -> boolExampleall (fn x => x>=2) [1,3,1,4];> val it = false : boolc○Michael R. Hansen, Spring 2005 – p.51/59


ExerciseDeclare a <strong>functions</strong>ubset(xs, ys)which is true when every element in the lists xs is in ys, and falseotherwise.Rememberall p xs ={truefalseif p(x) = true, for all elements x in xsotherwisec○Michael R. Hansen, Spring 2005 – p.52/59


<strong>Higher</strong>-<strong>order</strong> list <strong>functions</strong>: filterfilter p xs is the list of those elements x of xs where p(x) = true.DeclarationLibrary functionfun filter p [] = []| filter p (x::xs) = if p x then x :: filter p xselse filter p xs;> val filter = fn: (’a -> bool) -> ’a list -> ’a listExamplefilter Char.isAlpha [#"1", #"p", #"F", #"-"];> val it = [#"p", #"F"] : char listwhere Char.isAlpha c is true iff c ∈ {#"A", . . . , #"Z"} ∪ {#"a", . . . , #"z"}c○Michael R. Hansen, Spring 2005 – p.53/59


ExerciseDeclare a functioninter(xs, ys)which contains the common elements of the lists xs and ys — i.e.their intersection.Remember filter p xs is the list of those elements x of xs wherep(x) = true.c○Michael R. Hansen, Spring 2005 – p.54/59


<strong>Higher</strong>-<strong>order</strong> list <strong>functions</strong>: foldr (1)foldr ‘accumulates’ a function f from a ‘start value’ b over theelements of a list [x 1 , x 2 , . . . , x n ] (from right to left):foldr f b [x 1 , x 2 , . . . , x n−1 , x n ] = f(x 1 , f(x 2 , . . . , f(x n−1 , f(x n , b)) · · · ))} {{ }foldr f b [x 2 ,...,x n−1 ,x n ]DeclarationLibrary functionfun foldr f b [] = b| foldr f b (x::xs) = f(x,foldr f b xs);> val foldr =fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’bExample: the lenght functionfun length xs = foldr (fn (_,y) => y+1) 0 xs;> val length = fn : ’a list -> intlength [4,5,6];> val it = 3 : intc○Michael R. Hansen, Spring 2005 – p.55/59


<strong>Higher</strong>-<strong>order</strong> list <strong>functions</strong>: foldr (2)Accumulation of an infix operator ⊕. Evaluation is as followsfoldr op⊕ b [x 1 ,x 2 , . . . ,x n ] x 1 ⊕ (x 2 ⊕ · · · ⊕ (x n ⊕ b) · · · )Examples: Addition and Appendfun sumr xs = foldr op+ 0 xs;> val sumr = fn : int list -> intsumr [1,2,3,4];> val it = 10 : intfun append(xs,ys) = foldr op:: ys xs;> val append = fn : ’a list * ’a list -> ’a listappend([1,2,3],[4,5]);> val it = [1,2,3,4,5] : int listc○Michael R. Hansen, Spring 2005 – p.56/59


Exercise: union of setsLet an insertion function be declared byfun insert(x, ys) = if x member ys then ys else x::ysDeclare a union function on sets.Remember:foldr op⊕ b [x 1 ,x 2 , . . . ,x n ] x 1 ⊕ (x 2 ⊕ · · · ⊕ (x n ⊕ b) · · · )c○Michael R. Hansen, Spring 2005 – p.57/59


<strong>Higher</strong>-<strong>order</strong> list <strong>functions</strong>: foldl (1)foldl ‘accumulates’ a function f from a ‘start value’ b over theelements of a list [x 1 , x 2 , . . . , x n ] (from left to right):b{ }} ′{foldl f b [x 1 ,x 2 , . . . ,x n−1 ,x n ] = f(x n , f(x n−1 , . . . , f(x 2 , f(x 1 , b)) · · · ))} {{ }foldl f b ′ [x 2 ,...,x n−1 ,x n ]DeclarationLibrary functionfun foldl f b [] = b| foldl f b (x::xs) = foldl f (f(x,b)) xs;> val foldl =fn : (’a * ’b -> ’b) -> ’b -> ’a list -> ’bc○Michael R. Hansen, Spring 2005 – p.58/59


<strong>Higher</strong>-<strong>order</strong> list <strong>functions</strong>: foldl (2)Accumulation of an infix operator ⊕. Evaluation is as followsfoldl op⊕ b [x 1 ,x 2 , . . . ,x n ] (x n ⊕ · · · ⊕ (x 2 ⊕ (x 1 ⊕ b)) · · · )Examplesfun rev xs = foldl op:: [] xs;> val rev = fn : ’a list -> ’a listrev [1,2,3];> val it = [3, 2, 1] : int listc○Michael R. Hansen, Spring 2005 – p.59/59

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!