0% found this document useful (0 votes)
41 views22 pages

FoCS 202324 8

Here are the steps to transpose a matrix using curried functions in OCaml: 1. Define a recursive transpose function transp that takes a list of rows as argument. 2. Base case is an empty list, return empty list. 3. Recursive case: - Map List.hd over rows to get the first element of each row, giving the first row of transpose - Recursively call transp on the rows with the head removed to get the rest of the transpose - Cons the two results So transp maps over the rows, recursively transposing the remaining rows at each step to build up the transpose.

Uploaded by

odarefisher
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views22 pages

FoCS 202324 8

Here are the steps to transpose a matrix using curried functions in OCaml: 1. Define a recursive transpose function transp that takes a list of rows as argument. 2. Base case is an empty list, return empty list. 3. Recursive case: - Map List.hd over rows to get the first element of each row, giving the first row of transpose - Recursively call transp on the rows with the head removed to get the rest of the transpose - Cons the two results So transp maps over the rows, recursively transposing the remaining rows at each step to build up the transpose.

Uploaded by

odarefisher
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

Foundations of Computer Science

Lecture #8: Currying


Anil Madhavapeddy
2023-2024
Warm-Up
Warm-Up

Question 1: How many arguments does this function have?


let rec append = function
| ([], ys) -> ys
| (x::xs, ys) -> x :: append (xs,ys)
One (the argument is a tuple)

Question 2: What property does an inorder conversion of a


binary tree to a list preserve?
List will be sorted

Question 3: What is the depth of a balanced binary search tree with


n elements?
O (log n)
Functions
Functionsas
asValues
Values

In OCaml, functions can be


• passed as arguments to other functions,
• returned as results, say “lambda”
• put into lists, tree, etc.:
[(fun n -> n * 2); (fun n -> n * 3); (fun k -> k + 1)];;
- : (int -> int) list = [<fun>; <fun>; <fun>]
• but not tested for equality.
Functions
Functionswithout
withoutNames
Names

Functions Without Names

fun -> E is the function f such that f (x) = E


fn xx =>

2 The function (fnn => n * 2) is a doubling function.


The function (fun n -> n * 2) is a doubling function.
(fn(fun
n =>n n-> n * 2);;
*2);
> val
- : it
int= ->
fn int
: int -> int
= <fun>

n =>n n->
(fn(fun *2)n 17;
* 2) 17;;
> val it = 34
- : int = 34 : int
Functions
Functionswithout
withoutNames
Names

In : (fun n -> n * 2) 2;;


Out: - : int = 4

… can be given a name by a let declaration

In : let double = fun n -> n * 2;;


Out: val double : int -> int = <fun>

In : let double n = n * 2;;


Out: val double : int -> int = <fun>

In both cases:
In : double 2;
Out: - : int = 4
Functions
Functionswithout
withoutNames
Names

function can be used for pattern-matching:

function P1 -> E1 | … | Pn -> En

for example:

function 0 -> true | _ -> false

which is equivalent to:

fun x -> match x with 0 -> true | _ -> false

let is_zero = fun x -> match x with 0 -> true | _ -> false

let is_zero = function 0 -> true | _ -> false


Curried
CurriedFunctions
Functions

• Consider that a function can only have one argument


• Two options for multiple arguments:
1. tuples (e.g., pairs) [as seen in previous lectures]
2. a function that returns another function as a result
→ this is called currying (after H. B. Curry) 1

• Currying: expressing a function taking multiple arguments as


nested functions.

1 Credited to Schön nkel, but Schön nkeling didn’t catch on…


fi
fi
Curried
CurriedFunctions
Functions

Taking multiple arguments as nested functions, so,


instead of:

In : fun (n, k) -> n * 2 + k;;


Out: - : int * int -> int = <fun>

We can nest the fun-notation:


In : let it = fun k -> (fun n -> n * 2 + k);;
Out: val it : int -> int -> int = <fun>

k n
In : it 1 3;
Out: - : int = 7
CurriedFunctions
Curried Functions
Curried Functions
Curried Functions
A curried function returns another function as its result.
A curried function returns another function as its result.
val prefix = (fn a => (fn b => a^b));
let
val prefix
prefix =
= = (fun
(fn a -> (fun
a string
=> (fn -> b
b => -> a ^ b))
a^b));-> string)
803 > val prefix fn: (string
val prefix : string -> string -> string = <fun>
803 > val prefix = fn: string -> (string -> string)
prefix yields functions of type string -> string.
prefix yields functions of type string -> string.
val promote = prefix "Professor ";
> let
val promote
promote
val = ==
promote prefix
prefix "Professor
"Professor
fn: string "; ";;
-> string
>val
val promote
promote promote
"Mopp";:= string -> string
fn: string = <fun>
-> string
promote
> "Mopp";
"Professor Mopp" : string
promote "Mopp";;
> "Professor Mopp" : string
- : string = "Professor Mopp"
Shorthand
Shorthandfor
forCurried
CurriedFunctions
Functions
A function-returning function is just a function of two arguments

A function over pairs has type (σ1 × σ2 ) → τ.


A curried function has type σ1 → (σ2 → τ).
Shorthand for Curried Functions
This curried function is nicer than nested fun binders:

let prefix
A function-returning a bis=just
function a a^function
b;; of two arguments.

val
This curried prefix
function : string
syntax -> (nested
is nicer than string fn-> string)
binders:
de 804
Syntax: the symbol -> associates to the right
fun prefix a b = a^b;
> val prefix = ... as before
fun x1 x2 … xn -> E let f x1 x2 … xn = E

val dublet
= prefix
dub "Sir ";
= prefix “Lady ";;
val
> val dub dub : string
= fn: string ->
->string
string= <fun>

Curried functions allows partial application (to the first argument).


Partial
PartialApplication:
Application:AACurried
CurriedInsertion
InsertionSort
Sort
Key question: How to generalize <= to any data type?
let rec insort lessequal =
let rec ins = function
| x, [] -> [x]
| x, y::ys ->
if lessequal x y then x::y::ys
else y :: ins (x, ys)
in
let rec sort = function
| [] -> []
| x::xs -> ins (x, sort xs)
in
sort
lessequal sort

val insort : ('a -> 'a -> bool) -> ('a list -> 'a list )

IN OUT
Partial
PartialApplication:
Application:AACurried
CurriedInsertion
InsertionSort
Sort

Note: (<=) denotes comparison operator as a function

In : insort (<=) [5; 3; 9; 8];;


Out: - : int list = [3; 5; 8; 9]

In : insort (>=) [5; 3; 9; 8];;


Out: - : int list = [9; 8; 5; 3]

In : insort (<=) ["bitten"; "on"; "a"; "bee"];;


Out: - : string list = ["a"; "bee"; "bitten"; "on"]
map:the
map: the‘Apply
‘Applyto
toAll’
All’Functional
Functional

note: built-in as List.map

let rec map f = function


| [] -> []
| x::xs -> (f x) :: map f xs

In : map (fun s -> s ^ "ppy");


Out: -: string list -> string list = <fun>

In : map (fun s -> s ^ "ppy") ["Hi"; "Ho"];;


Out: - : string list = ["Hippy"; "Hoppy"]

In : map (map double) [[1]; [2; 3]];;


Out: - : int list list = [[2]; [4; 6]]
Example:
Example: Matrix Transpose
Example: MatrixTranspose
Matrix Transpose

⎛ ⎞
⎛ ⎞T a d
a b c ⎜ ⎟
⎝ ⎠ = ⎜b e⎟
⎝ ⎠
d e f
807 c f
fun hd (x::_) = x;
fun tl (_::xs) = xs;
let rec transp = function
| [] ([]::_)
fun transp :: _ -> []
= []
| rows
| transp -> (map
rows List.hd
= (map hd rows)
rows)::::
(transp (map List.tl rows))
(transp (map tl rows))
Example:
Example:Matrix
MatrixTranspose
Transpose

let rec transp = function


| [] :: _ -> []
| rows -> (map List.hd rows) ::
(transp (map List.tl rows))

In : let rows = [[1; 2; 3]; [4; 5; 6]];;

In : List.hd;;
Out: - : 'a list -> ‘a = <fun>
In : transp;
Out: - : 'a list list -> 'a list list

In : map List.hd rows;


Out: - : int list = [1; 4]
In : map tl rows;
Out: - : int list list = [[2; 3]; [5; 6]]
In : transp rows;
Out: - : int list list = [[1; 4]; [2; 5]; [3; 6]]
Review
Reviewof
ofMatrix
MatrixMultiplication
Multiplication

Review of Matrix Multiplication

⎛ ⎞
B1
! " ⎜ ⎟ ! "
⎜ .. ⎟
A1 ··· A k · ⎜ . ⎟ = A 1 B1 + · · · + A k Bk
⎝ ⎠
Bk

The right side is the vector dot product A⃗ · B⃗


Repeat for each row of A and column of B
onsists of a single column. Provided A and B contain the same number k
ments, multiplying them yields a 1 × 1 matrix whose single element is the
Review
Review of
ofMatrix
Matrix Multiplication
Multiplication
duct shown above.
If A is an m × k matrix and B is a k × n matrix then A × B is an m × n mat
each i and j , the (i, j ) element of A × B is the dot product of row i of A w
mn j of B. A B AxB
⎛ ⎞ ⎛ ⎞
2 0 ) * 2 0 4
⎜3 −1⎟ 1 0 2 ⎜−1 1 6⎟
⎜ ⎟
⎝0 1 ⎠ 4 −1 0 = ⎜
⎝ 4 −1 0⎠

1 1 5 −1 2

The (1,1) element above is computed by

(2, 0) · (1,(i,j)
For element 4) =of2×A 1x +B:0 × 4 = 2.
Coding matrixdot-product
multiplication of
in arow i and column
conventional j
programming language usua
lves three nested loops. It is hard to avoid mistakes in the subscripting, wh
n runs slowly due to redundant internal calculations.
Matrix Multiplication
Matrix in
Multiplication OCaml
in ML
Matrix Multiplication in ML

Dot product of two vectors—a curried function


let rec dotprod xs ys =
fun dotprod Matrix
[] Multiplication
[] in ML
= 0.0
match xs, ys with
| dotprod(x::xs)(y::ys)
| [], [] -> 0.0 = x*y + dotprod xs ys
809
| x::xs, y::ys -> x *. y +. dotprod xs ys
Dot product of twoMatrix product
vectors—a curried function
Q: What is the type of this function?
fun matprod(Arows,Brows)
fun dotprod [] [] == 0.0
float list -> float list -> float
| dotprod(x::xs)(y::ys)
let val cols = transp Brows = x*y + dotprod xs ys
e 809
in map (fn row => map (dotprod row) cols)
Matrix product
Arows
fun
let
endmatprod(Arows,Brows)
matprod arows brows = =
let val
let colscols
= transp brows
= transp in
Brows
map (fun row -> map (dotprod row) cols) arows
in map (fn row => map (dotprod row) cols)
Arows
end
Matrix
MatrixMultiplication
Multiplicationin OCaml
in ML

let rec matprod arows brows =


let cols = transp brows in
map (fun row -> map (dotprod row) cols) arows

inner map

x =
outer map

x =
List
ListFunctionals
Functionalsfor
forPredicates
Predicates
List Functionals for Predicates

let rec exists p = function


| [] -> exists
fun false p [] = false
| x::xs -> (p x) || (exists p xs)
| exists p (x::xs) = (p x) orelse exists p xs;
val exists : ('a -> bool) -> ('a list -> bool) = <fun>
> exists: ('a -> bool) -> ('a list -> bool)
810 let rec filter p = function
| [] -> []
fun filter p [] = []
| x::xs ->
| pfilter
if x thenp (x::xs) =
x :: if
filter p xs x :: filter p xs
p x then
else
else filter p xs;
filter p xs
val>filter
filter: ('a ->
: ('a -> bool)
bool)-> ('a list
->('a list->->'a'alist)
list)= <fun>

(A predicate is a boolean-valued function.)


List
ListFunctionals
Functionalsfor
forPredicates
Predicates

Dual to exists:
let rec all p = function
| [] -> true
| x::xs -> (p x) && all p xs

val all : ('a -> bool) -> 'a list -> bool = <fun>
Example:
> exists (fun x -> x mod 2 = 0) [1; 2; 3];;
- : bool = true

> filter (fun x -> x mod 2 = 0) [1; 2; 3];;


- : int list = [2]

> all (fun x -> x mod 2 = 0) [1; 2; 3];;


- : bool = false
Applications
Applicationsof
ofthe
thePredicate
PredicateFunctionals
Functionals
Applications of the Predicate Functionals

funlet member y xs= =


member(y,xs)
exists (fn
exists (funx x=>->x=y)
x = xs;
y) xs;;

let inter xs ys =
Slide 811 fun inter(xs,ys) =
filter (fun x -> member x ys) xs;;
filter (fn x => member(x,ys)) xs;

Testing whether two lists have no common elements

fun disjoint(xs,ys) =
let disjoint xs ys =
allall (fnx x->=>all
(fun all(fun
(fn yy ->
=> xx<>y)
<> y)ys)
ys)xs;
xs
> val disjoint = fn: ''a list * ''a list -> bool

You might also like