200 likes | 307 Views
유환조 Hwanjo Yu. CSED101 INTRODUCTION TO COMPUTING HIGH ORDER FUNCTION ( 고차함수 ). Review: Fibonacci sequence. Fibonacci sequence ( 피보나치 수열 ) 1, 1, 2, 3, 5, 8, 13, 21, … F n = F n-1 + F n-2 F 2 = F 1 = 1. Review: Fibonacci sequence. Input and output type: int - > int
E N D
유환조 Hwanjo Yu CSED101 INTRODUCTION TO COMPUTINGHIGH ORDER FUNCTION (고차함수)
Review: Fibonacci sequence • Fibonacci sequence (피보나치 수열) • 1, 1, 2, 3, 5, 8, 13, 21, … • Fn = Fn-1 + Fn-2 • F2 = F1 = 1
Review: Fibonacci sequence • Input and output type: int - > int • Argument is assumed to be >= 1 • fib n returns Fn in the fibonacci sequence • let rec fib n = • if n > 2 then fib (n-1) + fib (n-2) • else 1;; • Fib calls itself twice - fib (n-1) and fib (n-2), but the arguments will be decreased by one or two each time it is called, thus No infinite loop!
Review: Recursive function with unchanging argument • Q: what would be the output? • let k = 3;; • let rec f n = • if n > 1 then k * (f (n-1) ) + 1 • else 1;; • f 3;; • In f, k is fixed • When f is defined, k=3. Thus, an = 3an + 1 • If we want an=5an+1, then function f cannot be used. • How to let k be variable?
Review: Recursive function with unchanging argument • Define f_gen that has a variable k • let f_gen k n = • if n > 1 then k * (f_gen k (n-1) ) + 1 • else 1;; • You can call f_gen with a variable k, thus k is set at the time f is called rather than f is defined. • But, note that the value k is not changing when f_gen is called inside f_gen. Only the argument n is changing. • This is ok because k is not used in the terminal condition.
Review: Recursive function having multiple outputs • Example sequence • an = 2an-1 + bn-1 • bn = an-1 + 2bn-1 • a1 = p • b1 = q • let rec f_pair n = • Ifn > 1 then • Let (a, b) = f_pair (n-1) in (2*a + b, a + 2*b) • Else • (p, q);;
Review: Recursive function having multiple variable arguments • How to compute the GCD (Greatest Common Divisor) (최대공약수) of two values a and b? • E.g., a=12 and 6=18, gcd is 6 • Euclidean Algorithm: Keep subtracting smaller value from larger value until two values become equal • Let rec gcd a b = • If a > b then gcd (a-b) b • Else if a < b then gcd a (b-a) • Else a;;
High order function • First-order function • Functions that use basic types (e.g., int, float, string,..) as arguments or function output • All the functions we have seen so far are first-order functions • High-order function • Functions that use functions as arguments or function output
High-order function • Three types of high-order function • Use functions as arguments • Use functions as outputs • Use functions as both arguments and outputs
1. Function as argument • E.g., let app_zero f = f 0;; • val app_zero : (int -> 'a) -> 'a = <fun> • Why f has the type of int -> ‘a ? • let inc x = x + 1;; • let dec x = x - 1;; • app_zero inc;; • app_zero dec;;
1. Function as argument • # let app_twice_zero f = f (f 0);; • val app_twice_zero : (int -> int) -> int = <fun> • The argument is a function of (int -> int). Why? • The output is int. Why? • app_twice_zero inc;; • app_twice_zero dec;;
1. Function as argument • # let app_thrice_zero f = f (f (f 0));; • val app_thrice_zero : (int -> int) -> int = <fun> • # app_thrice_zero inc;; • - : int = 3 • # app_thrice_zero dec;; • - : int = -3
1. Function as argument • # let rec app_times_zero f n = • if n = 0 then 0 • else f (app_times_zero f (n - 1));; • val app_times_zero : (int -> int) -> int -> int = <fun> • # app_times_zero inc 10;; • - : int = 10 • # app_times_zero dec 10;; • - : int = -10
2. Function as output • # let incr_n n = fun x -> x + n;; • val incr_n : int -> int -> int = <fun> • “int -> int -> int” is equivalent to “int -> (int -> int)” • # (incr_n 10) 0;; • - : int = 10 • # (incr_n (-10)) 0;; • - : int = -10
2. Function as output • “# let inc = fun x -> x + 1;;” • is equivalent to “# let inc x = x + 1;;” • # let incr_n’ n x = x + n;; • val incr n’ : int -> int -> int = <fun> • incr_n’ and incr_n are equivalent! • # incr_n 10 0;; • - : int = 10 • # incr_n’ 10;; • - : int -> int = <fun>
2. Function as output • linear(x) = ax+b • let linear a b x = a * x + b;; • let linear a b = fun x -> a * x + b;; • let linear a = fun b x -> a * x + b;; • let linear a = fun b -> fun x -> a * x + b;; • let linear = fun a -> fun b -> fun x -> a * x + b;; • let linear = fun a b x -> a * x + b;; • T1 -> T2 -> … -> Tn-1 -> Tn is equivalent to • T1 -> (T2 -> … -> (Tn-1 -> Tn) …)
3. Function as argument and output • h(x) = f(x) + g(x) • let combine f g = let h x = f x + g x in h • let combine f g = fun x -> f x + g x • # let h = combine (fun x -> x + 1) (fun y -> y - 1) in h 0;; • - : int = 0 • # let combine f g = let h x = f x + g x in h;; • val combine : ('a -> int) -> ('a -> int) -> 'a -> int = <fun> • # let combine2 f g = let h x = f x + g x in h 0;; • val combine2 : (int -> int) -> (int -> int) -> int = <fun>
Type variable • # let combine f g = fun x -> f x + g x;; • val combine : ('a -> int) -> ('a -> int) -> 'a -> int = <fun> • f and g’s argument has the same type since x is shared, but the type of x is undetermined. • f and g return values of int type since they are used as operands of “+” • Note: The type of x is determined not in compile time but in runtime or when the function is actually called. • Why can’t it be determined in compile time?
Type variable • # let combine f g = fun x -> f x + g x;; • val combine : ('a -> int) -> ('a -> int) -> 'a -> int = <fun> • # combine (fun x -> x + 1) (fun y -> y - 1);; • - : int -> int = <fun> • # combine (fun x -> if x then 1 else 0) (fun y -> if y then 0 else 1);; • - : bool -> int = <fun> • Fun x -> (fun k -> if k ….) x + (fun y -> …) x
Type variable • Polymorphic function • functions having type variables • # let pair x y = (x, y);; • val pair : ’a -> ’b -> ’a * ’b = <fun> • # pair 0 0;; • - : int * int = (0, 0) • # pair 0 true;; • - : int * bool = (0, true)