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
CSE 341 22sp
CSE 341 22sp public
Commits
9e7512e5
Commit
9e7512e5
authored
May 09, 2022
by
James R. Wilcox
Browse files
L19 code
parent
43f079a5
Changes
1
Hide whitespace changes
Inline
Sidebyside
lecture/L19/lec19live.ml
0 → 100644
View file @
9e7512e5
(* currying recap *)
let
rec
filter
f
=
(
fun
xs
>
match
xs
with

[]
>
[]

x
::
xs'
>
if
f
x
then
x
::
((
filter
f
)
xs'
)
else
((
filter
f
)
xs'
))
let
is_even
x
=
x
mod
2
=
0
let
only_evens
xs
=
filter
is_even
xs
let
only_evens
=
filter
is_even
let
rec
filter_old_way
(
f
,
xs
)
=
match
xs
with

[]
>
[]

x
::
xs'
>
if
f
x
then
x
::
filter_old_way
(
f
,
xs'
)
else
filter_old_way
(
f
,
xs'
)
let
convert_from_tupled_to_curried
g
=
fun
x
>
fun
y
>
g
(
x
,
y
)
(* val convert_from_tupled_to_curried : ('a * 'b > 'c) > 'a > 'b > 'c = <fun> *)
let
filter_converted
f
=
convert_from_tupled_to_curried
filter_old_way
f
let
curry
g
x
y
=
g
(
x
,
y
)
let
uncurry
g
(
x
,
y
)
=
g
x
y
let
filter_unconverted_for_no_reason
f
=
uncurry
filter_converted
f
(*
Functional programming
 expressionoriented
 variant types and pattern matching
 firstclass functions ("functions are values")
 tour of closure idioms
 take a function as an argument
 return a function as a result
 a closure "captures" data from its defining environment to use later
 currying (and uncurrying)
TODAY:
 "combining functions"
 "let over lambda"
 refs and mutation
*)
(* function composition: takes two functions and returns a function *)
let
compose
=
fun
f
>
fun
g
>
fun
x
>
f
(
g
x
)
let
compose
f
g
=
fun
x
>
f
(
g
x
)
let
compose
f
g
x
=
f
(
g
x
)
let
add_one
n
=
n
+
1
let
double
n
=
2
*
n
let
add_one_then_double
=
compose
double
add_one
let
double_then_add_one
=
compose
add_one
double
(* proof that function composition is not commutative *)
let
(
>
)
x
f
=
f
x
let
n
=
10
>
add_one
>
double
let
n
=
10
>
add_one
>
double
let
m
=
10
>
double
>
add_one
(* compose_option *)
(*
if f has this type:
f : 'a > 'b option
can think of f as a function from 'a to 'b that can fail
If we have two such functions, what is the correct way to compose them?
g : 'b > 'c option
The "composition" of f and g, which should be a function of this type
'a > 'c option
If either step fails, the whole thing fails. If both succeed, then we return the result of g
*)
let
compose_option
(
g
:
'
b
>
'
c
option
)
(
f
:
'
a
>
'
b
option
)
:
'
a
>
'
c
option
=
fun
(
x
:
'
a
)
>
match
f
x
with

None
>
None

Some
(
y
:
'
b
)
>
g
y
let
ten_divided_by
n
=
if
n
=
0
then
None
else
Some
(
10
/
n
)
let
safe_hd
l
=
match
l
with

[]
>
None

x
::
_
>
Some
x
let
foo
=
compose_option
ten_divided_by
safe_hd
(* refs and mutation *)
let
x
=
10
let
r
=
ref
10
(* r has type "int ref" *)
(* the type "t ref"
 a mutable reference to a value of type t
 provides operations for reading and writing the reference
t ref IS NOT COMPATIBLE with type t
 build values of type "t ref"
 use "ref e" where e is any expression
 evaluate e to value v, and then create a new reference whose initial contents is v
 use values of type "t ref"
 read the value of the reference using "!e" where e is any expression
 evaluates to a value v
 OCaml's type system guarantees that v is a reference
 the result is the current contents of the reference
 write a value using "e1 := e2"
 evaluate e1 to value v1
 evaluate e2 to value v2
 OCaml's type system guarantees that v1 is a reference
 change the contents of the reference v1 to v2
*)
(* to read the ref, use "!" operator *)
let
y
=
!
r
let
_
=
r
:=
11
let
z
=
!
r
(* let w = 1 + r (* error! r is not an int *) *)
let
w
=
1
+
!
r
(*
let _ = x := 17 (* error! x is not an int ref *)
*)
let
_
=
r
:=
17
let
r2
:
int
option
ref
=
ref
None
(* ... many lines later ... *)
let
_
=
r2
:=
Some
5
(* let over lambda *)
(* idea: implement something like an ADT or an object *)
(* example:
map from keys to values (keys are ints and values are strings )
internal reprentation:
{ map: (int * string) list;
key_list: int list
}
internal invariant:
key_list = firsts map
*)
type
internal_rep
=
{
map
:
(
int
*
string
)
list
;
key_list
:
int
list
}
(* imagine there is only one keyvalue store ADT in the world *)
(* "public" *)
let
setup_library
()
=
let
the_map
=
ref
{
map
=
[]
;
key_list
=
[]
}
in
let
insert
k
v
=
let
m
=
!
the_map
in
the_map
:=
{
map
=
(
k
,
v
)
::
m
.
map
;
key_list
=
k
::
m
.
key_list
}
in
let
get_contents
()
=
(
!
the_map
)
.
map
in
(
insert
,
get_contents
)
let
(
insert
,
get_contents
)
=
setup_library
()
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