Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Logan Ince
cse34122wipublic
Commits
e7ffe55c
Commit
e7ffe55c
authored
Jan 16, 2022
by
Dan Grossman
Browse files
import unit3 code
parent
503d39ea
Changes
3
Hide whitespace changes
Inline
Sidebyside
lecture/lec08/lec08.ml
0 → 100755
View file @
e7ffe55c
(* CSE 341, Lecture 8 *)
(*#utop_prompt_dummy
let _ = UTop.set_show_box false
*)
(* Lecture 8: FirstClass Functions *)
let
double
x
=
x
*
2
let
incr
x
=
x
+
1
let
funcs
=
[
double
;
incr
]
let
rec
apply_funcs
(
fs
,
x
)
=
match
fs
with

[]
>
x

f
::
fs'
>
apply_funcs
(
fs'
,
f
x
)
(* binds foo to 201 *)
let
foo
=
apply_funcs
(
funcs
,
100
)
(* binds bar to 202 *)
let
bar
=
apply_funcs
(
List
.
rev
funcs
,
100
)
(* it should really bother us to write these functions separately *)
let
rec
increment_n_times_bothersome
(
n
,
x
)
=
if
n
=
0
then
x
else
1
+
increment_n_times_bothersome
(
n

1
,
x
)
let
rec
double_n_times_bothersome
(
n
,
x
)
=
if
n
=
0
then
x
else
2
*
double_n_times_bothersome
(
n

1
,
x
)
let
rec
tail_n_times_bothersome
(
n
,
xs
)
=
if
n
=
0
then
xs
else
List
.
tl
(
tail_n_times_bothersome
(
n

1
,
xs
))
(* much better: abstract the common pieces into a function *)
let
rec
n_times
(
f
,
n
,
x
)
=
if
n
=
0
then
x
else
f
(
n_times
(
f
,
n

1
,
x
))
(* we can now implement the 3 bothersome functions above in one line each *)
let
increment_n_times
(
n
,
x
)
=
n_times
(
incr
,
n
,
x
)
let
double_n_times
(
n
,
x
)
=
n_times
(
double
,
n
,
x
)
let
tail_n_times
(
n
,
xs
)
=
n_times
(
List
.
tl
,
n
,
xs
)
(* and nothing stops us from using n_times in places we didn't originally plan *)
let
triple
x
=
3
*
x
let
triple_n_times
(
n
,
x
)
=
n_times
(
triple
,
n
,
x
)
(* polymorphic but not higher order *)
let
rec
len
xs
=
match
xs
with

[]
>
0

_
::
xs'
>
1
+
len
xs'
(* higher order but not polymorphic *)
let
rec
times_until_zero
(
f
,
x
)
=
if
x
=
0
then
0
else
1
+
times_until_zero
(
f
,
f
x
)
(* two very useful and very common higherorder functions *)
let
rec
map
(
f
,
xs
)
=
match
xs
with

[]
>
[]

x
::
xs'
>
(
f
x
)
::
(
map
(
f
,
xs'
))
let
rec
filter
(
f
,
xs
)
=
match
xs
with

[]
>
[]

x
::
xs'
>
if
f
x
then
x
::
filter
(
f
,
xs'
)
else
filter
(
f
,
xs'
)
(* motivating anonymous functions *)
(* if we just need is_even for only_evens, better to use local function *)
let
only_evens2
xs
=
let
is_even
x
=
x
mod
2
=
0
in
filter
(
is_even
,
xs
)
(* actually, we could define it *right* where we need it *)
let
only_evens3
xs
=
filter
((
let
is_even
x
=
x
mod
2
=
0
in
is_even
)
,
xs
)
(* seems kind of silly to have a let expression whose body is the variable...
can we do better? *)
(* not like this. a let binding is not an expression! *)
(*
let only_evens4 xs =
filter ((let is_even x = x mod 2 = 0), xs)
*)
(* but an anonymous function is an expression! *)
let
only_evens5
xs
=
filter
((
fun
x
>
x
mod
2
=
0
)
,
xs
)
(* bad style: the 'if e then true else false' of functions *)
(* "unnecessary function wrapping" *)
let
tail_n_times_bad_style
(
n
,
xs
)
=
n_times
((
fun
ys
>
List
.
tl
ys
)
,
n
,
xs
)
(* good style *)
let
tail_n_times_good_style
(
n
,
xs
)
=
n_times
(
List
.
tl
,
n
,
xs
)
(*  *)
(* you can return functions from functions as well *)
let
mult_by_n
n
=
fun
x
>
n
*
x
(* notice how this is different from a simple multiplication function *)
let
multiply
(
n
,
x
)
=
n
*
x
(* look at the types! *)
(* another example *)
let
double_or_triple
f
=
if
f
7
then
fun
x
>
2
*
x
else
fun
x
>
3
*
x
let
roundabout_double
=
double_or_triple
(
fun
x
>
x

3
=
4
)
let
roundabout_nine
=
(
double_or_triple
(
fun
x
>
x
=
42
))
3
(*  *)
(* higherorder functions over our own recursive variant types *)
type
exp
=

Const
of
int

Negate
of
exp

Add
of
exp
*
exp

Multiply
of
exp
*
exp
let
rec
true
_of_all_constants
(
f
,
e
)
=
match
e
with

Const
n
>
f
n

Negate
e'
>
true
_of_all_constants
(
f
,
e'
)

Add
(
e1
,
e2
)
>
true
_of_all_constants
(
f
,
e1
)
&&
true
_of_all_constants
(
f
,
e2
)

Multiply
(
e1
,
e2
)
>
true
_of_all_constants
(
f
,
e1
)
&&
true
_of_all_constants
(
f
,
e2
)
let
all_even_constants
e
=
true
_of_all_constants
((
fun
x
>
x
mod
2
=
0
)
,
e
)
lecture/lec09/lec09.ml
0 → 100755
View file @
e7ffe55c
(* CSE 341, Lecture 9 *)
(*#utop_prompt_dummy
let _ = UTop.set_show_box false
*)
(* lexical scope examples to learn the rules *)
(* 1 *)
let
x
=
1
(* 2 *)
let
f
y
=
x
+
y
(* 3 *)
let
x
=
2
(* 4 *)
let
y
=
3
(* 5 *)
let
z
=
f
(
x
+
y
)
(* 1 *)
let
x
=
1
(* 2 *)
let
f
y
=
(* 2 a *)
let
x
=
y
+
1
in
(* 2 b *)
fun
q
>
x
+
y
+
q
(* 3 *)
let
x
=
3
(* 4 *)
let
g
=
f
4
(* 5 *)
let
y
=
5
(* 6 *)
let
z
=
g
6
(* 1 *)
let
f
g
=
(* 1 a *)
let
x
=
3
in
(* 1 b *)
g
2
(* 2 *)
let
x
=
4
(* 3 *)
let
h
y
=
x
+
y
(* 4 *)
let
z
=
f
h
(* let y = 5 *)
(* lexical scope examples to motivate the rules *)
(* f1 and f2 are always the same, no matter where used *)
let
f1
y
=
let
x
=
y
+
1
in
fun
z
>
x
+
y
+
z
let
f2
y
=
let
q
=
y
+
1
in
fun
z
>
q
+
y
+
z
let
h1
=
f1
7
let
h2
=
f2
7
let
x
=
17
(* irrelevant *)
let
a1
=
h1
4
let
a2
=
h2
4
(* f3 and f4 are always the same, no matter what argument is passed in *)
let
f3
g
=
let
x
=
3
in
(* irrelevant *)
g
2
let
f4
g
=
g
2
let
x
=
17
let
a3
=
f3
(
fun
y
>
x
+
y
)
let
a4
=
f4
(
fun
y
>
x
+
y
)
let
a5
=
f3
(
fun
y
>
17
+
y
)
let
a6
=
f4
(
fun
y
>
17
+
y
)
(* under dynamic scope, the call to g below would:
 try to add a string x to an int
 have an unbound variable y
even though g type checked! *)
let
x
=
"hi"
let
g
=
f1
7
let
z
=
g
4
(* lexical scope examples to leverage the rules *)
(* lexical scope very useful with higherorder functions *)
(* our first example of "currying"; will study and use
more soon
*)
let
rec
filter
f
=
(
fun
xs
>
match
xs
with

[]
>
[]

x
::
xs'
>
if
f
x
then
x
::
((
filter
f
)
xs'
)
else
((
filter
f
)
xs'
))
let
greater_than
x
=
fun
y
>
x
<
y
let
is_positive
=
greater_than
0
let
only_positives
=
filter
is_positive
let
all_greater
(
xs
,
n
)
=
(
filter
(
greater_than
n
))
xs
(* let's start using that e1 e2 e3 is (e1 e2) e3 *)
let
all_shorter
(
xs
,
s
)
=
filter
(
fun
x
>
String
.
length
x
<
String
.
length
s
)
xs
let
all_shorter'
(
xs
,
s
)
=
(* why is this potentially faster? *)
let
n
=
String
.
length
s
in
filter
(
fun
x
>
String
.
length
x
<
n
)
xs
let
rec
fold_left
(
f
,
acc
,
xs
)
=
match
xs
with

[]
>
acc

x
::
xs'
>
fold_left
(
f
,
(
f
(
acc
,
x
))
,
xs'
)
(* examples that do not capture private data *)
let
sum
xs
=
fold_left
((
fun
(
acc
,
x
)
>
acc
+
x
)
,
0
,
xs
)
let
only_positives
xs
=
fold_left
((
fun
(
acc
,
x
)
>
acc
&&
x
>=
0
)
,
true
,
xs
)
(* examples that *do* capture private data *)
let
count_in_range
(
lo
,
hi
,
xs
)
=
fold_left
((
fun
(
acc
,
x
)
>
acc
+
(
if
lo
<=
x
&&
x
<
hi
then
1
else
0
))
,
0
,
xs
)
let
are_all_shorter
(
xs
,
s
)
=
let
n
=
String
.
length
s
in
fold_left
((
fun
(
acc
,
x
)
>
acc
&&
String
.
length
x
<
n
)
,
true
,
xs
)
let
forall
(
f
,
xs
)
=
fold_left
((
fun
(
acc
,
x
)
>
acc
&&
f
x
)
,
true
,
xs
)
let
only_positives'
xs
=
forall
((
fun
x
>
x
>
0
)
,
xs
)
let
are_all_shorter'
(
xs
,
s
)
=
let
n
=
String
.
length
s
in
forall
((
fun
x
>
String
.
length
x
<
n
)
,
xs
)
lecture/lec10/lec10.ml
0 → 100755
View file @
e7ffe55c
(* CSE 341, Lecture 10 *)
(*#utop_prompt_dummy
let _ = UTop.set_show_box false
*)
(* function composition (righttoleft, like math) *)
let
compose
=
fun
f
>
fun
g
>
fun
x
>
f
(
g
x
)
(* infix notation for composition *)
let
(
%
)
=
compose
let
double_plus_one
x
=
compose
(
fun
x
>
x
+
1
)
(
fun
x
>
2
*
x
)
x
let
_
=
double_plus_one
3
(* "variablestyle" let binding is better style *)
let
double_plus_one
=
compose
(
fun
x
>
x
+
1
)
(
fun
x
>
2
*
x
)
let
_
=
double_plus_one
3
(* also nice to use the infix operator *)
let
double_plus_one
=
(
fun
x
>
x
+
1
)
%
(
fun
x
>
2
*
x
)
let
_
=
double_plus_one
3
let
sqrt_of_abs
i
=
Float
.
sqrt
(
float_of_int
(
Int
.
abs
i
))
let
sqrt_of_abs
i
=
(
Float
.
sqrt
%
float_of_int
%
Int
.
abs
)
i
let
sqrt_of_abs
=
Float
.
sqrt
%
float_of_int
%
Int
.
abs
let
_
=
sqrt_of_abs
(

8
)
(* pipeline operator (lefttoright) *)
(* actually builtin to OCaml, but here's the definition *)
let
(
>
)
x
f
=
f
x
let
sqrt_of_abs
i
=
i
>
Int
.
abs
>
float_of_int
>
Float
.
sqrt
let
_
=
sqrt_of_abs
(

8
)
(* also lefttoright *)
let
pipeline_option
(
f
,
g
)
=
fun
x
>
match
f
x
with

None
>
None

Some
y
>
g
y
let
sqrt_if_positive
=
pipeline_option
((
fun
i
>
if
i
>
0
then
Some
(
float_of_int
i
)
else
None
)
,
(
fun
x
>
Some
x
)
%
sqrt
)
let
_
=
sqrt_if_positive
3
let
_
=
sqrt_if_positive
(

3
)
(*  *)
(* Currying *)
let
sorted3_tuple
(
x
,
y
,
z
)
=
x
<=
y
&&
y
<=
z
let
_
=
sorted3_tuple
(
7
,
9
,
11
)
let
sorted3
=
fun
x
>
fun
y
>
fun
z
>
x
<=
y
&&
y
<=
z
let
_
=
((
sorted3
7
)
9
)
11
let
_
=
sorted3
7
9
11
let
sorted3_spaces_fun
=
fun
x
y
z
>
x
<=
y
&&
y
<=
z
let
_
=
sorted3_spaces_fun
7
9
11
let
sorted3_spaces
x
y
z
=
x
<=
y
&&
y
<=
z
let
_
=
sorted3_spaces
7
9
11
(* fold again, but now curried *)
(* this exact definition is in the stdlib at List.fold_left *)
let
rec
fold_left
f
acc
xs
=
match
xs
with

[]
>
acc

x
::
xs'
>
fold_left
f
(
f
acc
x
)
xs'
let
sum_meh_style
xs
=
fold_left
(
fun
acc
x
>
acc
+
x
)
0
xs
let
sum_good_style
=
fold_left
(
fun
acc
x
>
acc
+
x
)
0
let
remove_negs_meh
xs
=
List
.
filter
(
fun
x
>
x
>=
0
)
xs
(* partial application and currying allows us to use "variablestyle" let *)
let
remove_negs
=
List
.
filter
(
fun
x
>
x
>=
0
)
let
remove_all
n
=
List
.
filter
(
fun
x
>
x
<>
n
)
let
remove_zeros
=
remove_all
0
let
increment_all
=
List
.
map
(
fun
x
>
x
+
1
)
(* in the library as List.exists *)
let
rec
exists
p
xs
=
match
xs
with

[]
>
false

x
::
xs'
>
p
x

exists
p
xs'
let
exists
p
xs
=
List
.
fold_left
(
fun
acc
x
>
acc

p
x
)
false
xs
let
exists
p
=
List
.
fold_left
(
fun
acc
x
>
acc

p
x
)
false
(* in the library as List.for_all *)
let
forall
p
=
List
.
fold_left
(
fun
acc
x
>
acc
&&
p
x
)
true
let
has_zero
=
exists
(
fun
x
>
x
=
0
)
let
no_zeros
=
forall
(
fun
x
>
x
<>
0
)
(* currying is the norm in OCaml, even if partial application unlikely *)
let
rec
append
xs
ys
=
match
xs
with

[]
>
ys

x
::
xs'
>
x
::
append
xs'
ys
(* revisit compose *)
let
compose_shorter
f
g
x
=
f
(
g
x
)
(* converting between curried and tupled versions of a function *)
let
curried_of_paired
f
x
y
=
f
(
x
,
y
)
let
paired_of_curried
f
(
x
,
y
)
=
f
x
y
(* more verbose but less "tricky" versions of the above: *)
(*
let curried_of_paired f = fun x > fun y > f (x, y)
let paired_of_curried f = fun (x, y) > (f x) y
*)
(* check out how much the types tell us above and here: *)
let
swap_tupled
f
(
x
,
y
)
=
f
(
y
,
x
)
let
swap_curried
f
x
y
=
f
y
x
let
rec
range
(
lo
,
hi
)
=
if
lo
>
hi
then
[]
else
lo
::
range
(
lo
+
1
,
hi
)
(* no problem using range as curried even though it's tupled 
convert it
*)
let
countup
=
curried_of_paired
range
0
let
_
=
countup
5
(******** value restriction *********)
(*
let remove_empty_lists = List.filter (fun x > List.length x > 0)
(* look at the type *)
let _ = remove_empty_lists [[]; [1]]
(* *now* look at the type!! *)
let _ = remove_empty_lists [[]; [true]]
(* oh no! *)
*)
(* workaround 1: go back to bad style :\ *)
let
remove_empty_lists
ls
=
List
.
filter
(
fun
x
>
List
.
length
x
>
0
)
ls
let
_
=
remove_empty_lists
[[];
[
1
]]
let
_
=
remove_empty_lists
[[];
[
true
]]
(*  *)
(* refs and mutable state *)
let
x
=
ref
42
let
y
=
ref
42
let
z
=
x
let
_
=
x
:=
43
let
w
=
!
x
+
!
z
(* does not typecheck: *)
(* let _ = x + 1 *)
(*  *)
(* callback library *)
let
callbacks
:
(
int
>
unit
)
list
ref
=
ref
[]
let
on_key_event
f
=
callbacks
:=
f
::
!
callbacks
(* like map, but produces no data *)
(* in the library as List.iter *)
let
rec
iter
f
xs
=
match
xs
with

[]
>
()

x
::
xs'
>
f
x
;
iter
f
xs'
let
do_key_event
i
=
List
.
iter
(
fun
f
>
f
i
)
!
callbacks
(* callback client *)
let
times_pressed
=
ref
0
(* actually builtin, but here's the definition *)
let
incr
int_ref
=
int_ref
:=
!
int_ref
+
1
let
()
=
on_key_event
(
fun
_
>
incr
times_pressed
)
let
()
=
do_key_event
97
let
()
=
do_key_event
98
let
()
=
do_key_event
99
let
_
=
!
times_pressed
let
print_if_pressed
i
=
on_key_event
(
fun
j
>
if
i
=
j
then
print_endline
(
"pressed "
^
string_of_int
i
)
else
()
)
let
()
=
do_key_event
97
let
()
=
print_if_pressed
122
let
()
=
do_key_event
98
let
()
=
do_key_event
122
let
_
=
!
times_pressed
(*  *)
(* ADTs via closures *)
type
set
=
S
of
{
insert
:
int
>
set
;
member
:
int
>
bool
;
size
:
unit
>
int
;
}
let
empty_set
=
let
rec
make_set
xs
=
(* xs is "private field" in result *)
let
contains
i
=
List
.
mem
i
xs
in
(* contains is "private method" *)
S
{
insert
=
(
fun
i
>
if
contains
i
then
make_set
xs
else
make_set
(
i
::
xs
));
member
=
contains
;
size
=
(
fun
()
>
List
.
length
xs
)
}
in
make_set
[]
(* client *)
let
_
=
let
S
s1
=
empty_set
in
let
S
s2
=
s1
.
insert
34
in
let
S
s3
=
s2
.
insert
34
in
let
S
s4
=
s3
.
insert
19
in
s4
.
size
()
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment