HigherOrderFunctions

download HigherOrderFunctions

of 50

Transcript of HigherOrderFunctions

  • 7/30/2019 HigherOrderFunctions

    1/50

    Lecture 7: Higher-Order Functions

    Jean-Noel Monette

    Functional Programming 1

    September 25, 2012

    Based on notes by Pierre Flener, Sven-Olof Nystrom

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 1 / 50

  • 7/30/2019 HigherOrderFunctions

    2/50

    Today

    1 Introductory Examples

    2 Higher-order functions on lists

    3 More Examples

    4 Example: Polymorphic Ordered Binary Tree

    5 Higher-Order Functions on Trees

    6 Lazy Evaluation

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 2 / 50

  • 7/30/2019 HigherOrderFunctions

    3/50

    Introductory Examples

    Table of Contents

    1 Introductory Examples

    2 Higher-order functions on lists

    3 More Examples

    4 Example: Polymorphic Ordered Binary Tree

    5 Higher-Order Functions on Trees

    6 Lazy Evaluation

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 3 / 50

  • 7/30/2019 HigherOrderFunctions

    4/50

    Introductory Examples

    Reminder

    An anonymous function: a function without a name.

    fun double x = 2xval double = fn x => 2x

    are equivalent.So are

    double 42

    (fn x =>

    2x) 42

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 4 / 50

    I d E l

  • 7/30/2019 HigherOrderFunctions

    5/50

    Introductory Examples

    Insertion Sort on Integers

    fun insert x [] = [x]| insert x (y :: ys) =

    if x < y

    then x : : y : : y selse y :: ( insert x ys );

    fun isort [] = []| isort (x :: xs) =

    insert x ( isort xs );

    How to sort in general (not only integer)?

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 5 / 50

    I t d t E l

  • 7/30/2019 HigherOrderFunctions

    6/50

    Introductory Examples

    Insertion Sort on any type

    fun insert order x [] = [x]| insert order x (y :: ys) =

    if order(x,y)then x : : y : : y s

    else y :: ( insert order x ys );

    fun isort order [] = []| isort order (x :: xs) =

    insert order x ( isort order xs );What is the type of the different functions?Exercise (at home): redefine the merge sort to be polymorphic.

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 6 / 50

    Introductory Examples

  • 7/30/2019 HigherOrderFunctions

    7/50

    Introductory Examples

    Example (cont.)

    > isort (op isort (op >) [6,3,0,1,7,8,5,9,2,4];val it = [9,8,7,6,5,4,3,2,1,0]: int list> isort String.< [one,two,three,four, five , six ,seven ];

    val it = [five ,four,one,seven,six ,three,two]: string list> isort (op int list> isort String.< ;val it = fn: string list > string list> isort (fn (( ,s1 ),( ,s2)) => String.

  • 7/30/2019 HigherOrderFunctions

    8/50

    Introductory Examples

    Higher-order functions

    A higher-order function: a function that either

    takes functions as arguments or

    returns functions as result.Remarks

    This is hard to do in an imperative programming language

    This is a very powerful mechanism

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 8 / 50

    Introductory Examples

  • 7/30/2019 HigherOrderFunctions

    9/50

    Introductory Examples

    Reflection on the definition of sum

    fun sum [] = 0| sum (x:: l ) = x + sum l;

    There are only two places in the function definition that are specific forcomputing a sum:

    +, combining data

    0, result for empty list

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 9 / 50

    Introductory Examples

  • 7/30/2019 HigherOrderFunctions

    10/50

    Introductory Examples

    A generalization

    Lets define a function reduce so thatreduce + 0 is equal to sum

    fun reduce f z [] = z| reduce f z (x:: l) = f(x,reduce f z l );

    fun reduce f z = (fn [] => z| (x :: l ) => f(x,reduce f z l ));

    Note the similarity between reduce and sum.

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 10 / 50

    Introductory Examples

  • 7/30/2019 HigherOrderFunctions

    11/50

    y p

    Generalization (cont.)

    Now, sum can be defined as

    fun sum xs = reduce (op +) 0 xs;

    val sum = reduce (op +) 0;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 11 / 50

    Introductory Examples

  • 7/30/2019 HigherOrderFunctions

    12/50

    y p

    Other uses of reduce

    What will the following compute?

    reduce (op ) 1 [1,2,3,4];

    reduce Int .max 0 [1,2,3,44,5,6];

    reduce (fn(x,y) => x::y) [] [1,2,3,4];

    reduce (fn(x,y) => x::y) [5,6,7] [1,2,3,4];

    reduce (fn(x,y) => x::x::y) [] [1,2,3,4];

    reduce (op @) [] [[1,2],[34],[5,6,7,89]];

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 12 / 50

    Introductory Examples

  • 7/30/2019 HigherOrderFunctions

    13/50

    y

    Function composition

    A function that takes two functions and returns a function!

    fun o (f,g) x = f(g(x));

    infix o;

    o is predefined. No need to define it.

    fun add1 x = x + 1;(add1 o add1) 42;

    Exercise: Find values id1 and id2 so that

    (id1 o f) x = f x ( for all f , x )

    (f o id2) x = f x ( for all f , x )

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 13 / 50

    Introductory Examples

  • 7/30/2019 HigherOrderFunctions

    14/50

    Pair

    Another way of building functions:> fun pair (f,g) x = (f x, g x);val pair = fn: ( a > b) (a > c) > a > b c

    > pair(add1,add1 o add1);val it = fn: int > int int> it 42;val it = (43,44): int int

    >

    pair(pair(add1,add1 o add1), add1);val it = fn: int > (int int) int> it 42;val it = ((43,44),43): ( int int) int

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 14 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    15/50

    Table of Contents

    1 Introductory Examples

    2 Higher-order functions on lists

    3 More Examples

    4 Example: Polymorphic Ordered Binary Tree

    5

    Higher-Order Functions on Trees

    6 Lazy Evaluation

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 15 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    16/50

    Higher-order functions on lists

    Several functions are very useful to define operations on lists.

    > map;val it = fn: ( a > b) > a list > b list>

    foldr;val it = fn: ( a b > b) > b > a list > b> foldl ;val it = fn: ( a b > b) > b > a list > b> List. filter ;

    val it = fn: ( a > bool) > a list > a listThose functions are predefined in ML, but we will see the details.

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 16 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    17/50

    The map function

    Apply the same operation on all the elements of a list.( PRE: (none)

    POST: [f(a 1), f (a 2 ), ..., f (a n )], if L = [a 1,a 2, ..., a n] )> fun map f [ ] = [ ]

    | map f (x :: xs) = f x :: map f xs;val map = fn: (a > b) > a list > b list

    > fun square x = xx;val square = fn: int > int>

    map square [1,2,3,4];val it = [1,4,9,16]: int list> map (fn(x)=> if x < 3 then 0 else x) [1,2,3,4];val it = [0,0,3,4]: int list

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 17 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    18/50

    The map function (cont.)

    > map square;val it = fn: int list > int list> map (map square);val it = fn: int list list > int list list> map (map square) [[1,2,34],[5]];val it = [[1,4,1156],[25]]: int list list> map String. bool list

    > map String.< [(a,ab), ( hello , bye )];val it = [true , false ]: bool list

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 18 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    19/50

    Foldr and foldl

    fun foldr f b [] = b| foldr f b (x :: xs) = f(x, foldr f b xs );

    fun foldl f b [] = b| foldl f b (x :: xs) = foldl f (f (x, b)) xs;

    Do they remind you of any function you have seen before?Which one is tail-recursive?

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 19 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    20/50

    Examples

    Sum the elements of the list.

    foldr (op +)0

    [0,2,21,4,6];foldl (op +)

    0[0,2,21,4,6];

    Are they equivalent?Which one would you use? Why?

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 20 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    21/50

    Examples (cont.)

    Check that all elements of a list are even

    foldr (fn (x,y) => y andalso x mod 2 = 0)true[0,2,21,4,6];

    foldl (fn (x,y) => y andalso x mod 2 = 0)true[0,2,21,4,6];

    Are they equivalent?Which one would you use? Why?

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 21 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    22/50

    Examples (cont.)

    Compare

    foldr (op ::) [];

    foldl (op ::) [];

    Are they equivalent?

    Which one would you use? Why?

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 22 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    23/50

    Examples (cont.)

    What does this function compute?

    fun firstEven (x,NONE) =if x mod 2 = 0 then SOME x else NONE

    | firstEven ( , SOME y) = SOME y;

    Compare

    foldl firstEven NONE;foldr firstEven NONE;

    Are they equivalent?

    Which one would you use for what?

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 23 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    24/50

    More examples

    Try

    foldl (fn(x,n) => n+1) 0

    foldr (fn(x,n) => n+1) 0

    foldr (fn(x,n) => x) 0

    foldl (fn(x,n) => x) 0

    fun mystery f = foldr (fn (x,n) => f x :: n) [];

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 24 / 50

    Higher-order functions on lists

  • 7/30/2019 HigherOrderFunctions

    25/50

    Filter

    ( PRE: (none)POST: the list of elements of the list for which p is true )

    fun filter p [] = []| filter p (x :: xs) =

    if p x

    then

    x :: filter p xselse

    filter p xs ;

    Examples:

    filter (fn(x) => x x

  • 7/30/2019 HigherOrderFunctions

    26/50

    Table of Contents

    1 Introductory Examples

    2 Higher-order functions on lists

    3 More Examples

    4 Example: Polymorphic Ordered Binary Tree

    5 Higher-Order Functions on Trees

    6 Lazy Evaluation

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 26 / 50

    More Examples

  • 7/30/2019 HigherOrderFunctions

    27/50

    Folding over integers

    Fold over integers (really natural numbers) gives us a general way torecurse over natural numbers

    fun foldint f b 0 = b| foldint f b n = foldint f (f (b,n)) (n1);foldint (op + ) 0 5;foldint (op ) 1 5;foldint (fn ((a,b), ) => (a+b, a)) (1,1) 10;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 27 / 50

    More Examples

    ( )

  • 7/30/2019 HigherOrderFunctions

    28/50

    Folding over integers (cont.)

    fun td a = foldint(fn (b,n) => b andalso (n if td n then n:: l else l )[] n;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 28 / 50

    More Examples

  • 7/30/2019 HigherOrderFunctions

    29/50

    twice and ntimes

    We can define a function that tells us how to do something twice:

    fun twice f = f o f ;fun add1 x = x+1;

    twice add1 56;Or more generally, do something n times:

    fun ntimes 0 f x = x| ntimes n f x = ntimes (n1) f (f x);

    ntimes 42 twice ;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 29 / 50

    Example: Polymorphic Ordered Binary Tree

    T bl f C

  • 7/30/2019 HigherOrderFunctions

    30/50

    Table of Contents

    1 Introductory Examples

    2 Higher-order functions on lists

    3 More Examples

    4 Example: Polymorphic Ordered Binary Tree

    5 Higher-Order Functions on Trees

    6 Lazy Evaluation

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 30 / 50

    Example: Polymorphic Ordered Binary Tree

    Bi h

  • 7/30/2019 HigherOrderFunctions

    31/50

    Binary search trees

    A Binary search tree is a binary tree which is ordered, i.e.

    All values in the left subtree are smaller than the value of the root.All values in the right subtree are larger than the value of the root.

    The order can be defined for any type.We will consider the values to be pairs:

    The first element is the key.The second is the value that we want to associate with the key.

    i.e. we define a dictionary.

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 31 / 50

    Example: Polymorphic Ordered Binary Tree

    Bi h t

  • 7/30/2019 HigherOrderFunctions

    32/50

    Binary search trees

    datatype (a , b) bsTree= Void| Bst of ( a , b) bsTree ( a b) ( a , b) bsTree;

    Note:

    We want the key to be of some equality type.

    The order is not part of the datatype.

    It is possible to build a bsTree that is not ordered.

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 32 / 50

    Example: Polymorphic Ordered Binary Tree

    R t i i l t

  • 7/30/2019 HigherOrderFunctions

    33/50

    Retrieving an element

    ( PRE: the tree is ordered.POST: if the tree contains the key, return the corresponding

    value embedded in SOME. NONE otherwise)

    fun retrieve lessThan k Void = NONE| retrieve lessThan key (Bst ( left ,( k, v ), right )) =

    if key = k then SOME velse if lessThan (key,k) then retrieve lessThan key leftelse retrieve lessThan key right ;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 33 / 50

    Example: Polymorphic Ordered Binary Tree

    R t i i g l t ( t )

  • 7/30/2019 HigherOrderFunctions

    34/50

    Retrieving an element (cont.)

    We may use the datatype order instead:

    fun retrieve compare k Void = NONE| retrieve compare key (Bst ( left ,( k, v ), right )) =

    case compare (key,k)of EQUAL => SOME v| LESS => retrieve compare key left| GREATER => retrieve compare key right;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 34 / 50

    Example: Polymorphic Ordered Binary Tree

    Inserting an element

  • 7/30/2019 HigherOrderFunctions

    35/50

    Inserting an element

    ( PRE: The tree is ordered.POST: If the tree contains the key, a tree with the value replaced .

    Otherwise, a tree with the (key, value) pair insertedsuch that the tree is ordered .)

    fun insert compare (key,value) Void = Bst(Void,(key, value ),Void)| insert compare (key,value) (Bst ( left ,(k, v ), right )) =

    case compare (key,k)of EQUAL => Bst (left,(k,value),right )| LESS => Bst(insert compare (key,value) left , (k,v ), right )

    | GREATER => Bst(left,(k,v),insert compare (key,value) right );Exercise: Specify and realise the exists and delete functions. (Delete is abit more difficult.)

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 35 / 50

    Example: Polymorphic Ordered Binary Tree

    Functional Datatype

  • 7/30/2019 HigherOrderFunctions

    36/50

    Functional Datatype

    Consider again the previous definition of bsTree:

    The functional argument compare must be passed at each call

    The compare order is not global to the binary search tree

    Lets introduce the order in a new datatype:

    datatype (a , b) bsTree= Void| Bst of ( a , b) bsTree ( a b) ( a , b) bsTree;

    type a ordering = a a > order;

    datatype (a, b) obsTree= OrdBsTree of a ordering ( a , b) bsTree;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 36 / 50

    Example: Polymorphic Ordered Binary Tree

    Inserting an element

  • 7/30/2019 HigherOrderFunctions

    37/50

    Inserting an element

    fun emptyTree compare = OrdBsTree (compare, Void);

    fun insert (key, value) OrdBsTree (compare, tree) =let fun insert Void = (key,value)

    | insert (Bst ( left ,(k,v ), right )) =case compare (key,k)of EQUAL => Bst (left,(k,value),right)| LESS => Bst(insert left , (k, v ), right )

    | GREATER =>

    Bst(left,(k,v),insert right )in OrdBstTree (compare, insert tree ) end;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 37 / 50

    Higher-Order Functions on Trees

    Table of Contents

  • 7/30/2019 HigherOrderFunctions

    38/50

    Table of Contents

    1 Introductory Examples

    2 Higher-order functions on lists

    3 More Examples

    4 Example: Polymorphic Ordered Binary Tree

    5 Higher-Order Functions on Trees

    6 Lazy Evaluation

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 38 / 50

    Higher-Order Functions on Trees

    Higher-Order Functions on Trees

  • 7/30/2019 HigherOrderFunctions

    39/50

    Higher-Order Functions on Trees

    Like for lists, it is possible to define generic functions on trees.

    mapbt applies some function on all elements of the tree.

    Different folding functions can be defined.

    We cover here binary trees, but the same might be done for othertypes of trees.

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 39 / 50

    Higher-Order Functions on Trees

    Mapping and reducing a binary tree

  • 7/30/2019 HigherOrderFunctions

    40/50

    Mapping and reducing a binary tree

    datatype (a) btree = Vd | Bt of a a btree a btree;

    fun mapbt f Vd = Vd| mapbt f (Bt(v, l , r )) = Bt(f v, mapbt f l , mapbt f r );

    fun reducebt f z Vd = z| reducebt f z (Bt(v, l , r )) = f (v,reducebt f z l ,reducebt f z r );

    mapbt abs;reducebt (fn ( v , l , r ) => 1 + l + r) 0;

    reducebt (fn ( v , l , r ) => 1 + Int.max(l,r)) 0;reducebt (fn ( v , l , r ) => l @ [v] @ r) [];reducebt (fn ( v , l , r ) => Bt(v,r,l)) Vd;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 40 / 50

    Higher-Order Functions on Trees

    Exercises

  • 7/30/2019 HigherOrderFunctions

    41/50

    Exercises

    Use reducebt to compute if a btree is ordered (according to somegiven order).

    Use reducebt to transform a btree into a bsTree.

    Define a function map on trees (as in assignment 2).

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 41 / 50

    Lazy Evaluation

    Table of Contents

  • 7/30/2019 HigherOrderFunctions

    42/50

    Table of Contents

    1 Introductory Examples

    2 Higher-order functions on lists

    3 More Examples

    4 Example: Polymorphic Ordered Binary Tree

    5 Higher-Order Functions on Trees

    6 Lazy Evaluation

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 42 / 50

    Lazy Evaluation

    Lazy evaluation

  • 7/30/2019 HigherOrderFunctions

    43/50

    Lazy evaluation

    Idea: Do not evaluate the arguments of a function call before weknow that they will be needed.

    Similarly, when computing a datastructure or a list, dont compute

    the components before we know that they are needed.In a functional programming language with lazy evaluation, it ismeaningful to write a function that creates (for example) a list of allintegers or a list of all prime numbers. A second function might callthe first and print the first 100.

    fun ints n = n :: ints (n+1); does not terminate in SML.

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 43 / 50

    Lazy Evaluation

    Simulating lazy evaluation

  • 7/30/2019 HigherOrderFunctions

    44/50

    S g y

    In SML (or any other programming language with eager evaluation andhigher-order functions) we can simulate a value computed by lazyevaluation by a function.

    Indeed, in the following code, the addition is only perfomed in the secondline:

    val lazyFive = (fn () => 3 + 2);val five = lazyFive ();

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 44 / 50

    Lazy Evaluation

    Example: lazy mult

  • 7/30/2019 HigherOrderFunctions

    45/50

    p y

    fun mult x y =if x = 0 then 0 else x y;

    fun lazyMult x y =if x() = 0 then 0 else x() y();

    What are the types of the functions?

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 45 / 50

    Lazy Evaluation

    Example: lazy mult

  • 7/30/2019 HigherOrderFunctions

    46/50

    p y

    mult (11) (3 div 0);(fn x => fn y => if x=0 then 0 else xy) (11) (3 div 0);(fn x => fn y => if x=0 then 0 else xy) 0 (3 div 0);(fn y => if 0=0 then 0 else 0y) (3 div 0);(fn y => if 0=0 then 0 else 0y) ( raise Div);raise Div;

    lazyMult (fn() => 11) (fn() => 3 div 0);(fn x => fn y => if x()=0 then 0 else x()y()) (fn() => 11) (fn() => 3 div 0);(fn y => if (fn() => 11)()=0 then 0 else (fn() => 11)()y()) (fn() => 3 div 0);if (fn() => 11)()=0 then 0 else (fn() => 11)()(fn() => 3 div 0)();

    if 0=0 then 0 else (fn() =>

    1

    1)()

    (fn() =>

    3 div 0)();if true then 0 else (fn() => 11)()(fn() => 3 div 0)();0;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 46 / 50

    Lazy Evaluation

    Simulating infinite sequences

  • 7/30/2019 HigherOrderFunctions

    47/50

    g q

    Infinite sequences can either be represented:

    as a function f i = x i where xi is the ith element

    or as a pair datatype composed of

    the first value, anda function that gives us the next pair.

    Question: how would you define basic list operations such as hd, tl, mapfor these representations?

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 47 / 50

    Lazy Evaluation

    First approach

  • 7/30/2019 HigherOrderFunctions

    48/50

    fun ints i = i;fun zeroes i = 0;

    fun fToList n f =let fun aux m = if m>=n then []

    else f m :: aux (m+1);in aux 0 end;

    fToList 7 ints ;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 48 / 50

    Lazy Evaluation

    Second approach

  • 7/30/2019 HigherOrderFunctions

    49/50

    datatype (a) seq = Pair of a (unit > a seq);

    fun ints n = Pair(n,(fn () => ints (n+1)));

    fun sToList 0 f = []| sToList n f = let val Pair(v,next) = f()

    in v :: sToList (n1) next end;

    sToList 7 (fn () => ints 0);

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 49 / 50

    Lazy Evaluation

    End Note

  • 7/30/2019 HigherOrderFunctions

    50/50

    A good implementation of a lazy languages must make sure that the valueof a subexpression is never computed more than once. The solutionspresented here do not have that property.

    val lazyFive = (fn () => 3 + 2);val six = lazyFive() + 1;val seven = lazyFive() + 2;val height = lazyFive() + 3;

    Jean-Noel Monette (UU) Lecture 7: Higher-Order Functions 50 / 50