restructure + lecutre 07
This commit is contained in:
96 files changed
+458
-4
No files matched your search
@@ -0,0 +1,279 @@
|
||||
(*
|
||||
COMPILE = ocamlc -o outfile infile.ml
|
||||
|
||||
UTOP = #use "filename.ml";;
|
||||
*)
|
||||
|
||||
(*
|
||||
Ocaml is thankfully garbage collected
|
||||
|
||||
Expressions must end with double semi colon
|
||||
e.g. let name = "Bread";;
|
||||
|
||||
expressions can be evaluated to a value
|
||||
|
||||
ocaml is a statically typed and strongly typed language
|
||||
meaning that at compile time the type of a variable will
|
||||
be known. The compiler uses type inference to determine the
|
||||
type of a variable that you dont need to specify;
|
||||
|
||||
e.g.
|
||||
*)
|
||||
|
||||
(* string type *)
|
||||
"Hello World";;
|
||||
|
||||
(* character type *)
|
||||
'A';;
|
||||
|
||||
(* integer type *)
|
||||
50;;
|
||||
|
||||
(* floating type *)
|
||||
20.3;;
|
||||
|
||||
(*
|
||||
OPERATIONS
|
||||
|
||||
you have basic operations such as
|
||||
+, -, *, /, that works with integer types
|
||||
|
||||
to do these operations with floating point
|
||||
numbers you need to use the following
|
||||
|
||||
+., -., *., /., notice the "." after the operator
|
||||
|
||||
-----------------------------------------------
|
||||
|
||||
MODULE does not use the % sign
|
||||
|
||||
use "mod" e.g.
|
||||
|
||||
3 mod 2;; - : int = 1 (* evaluates to 1 *)
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
NOT uses the word "not" instead of "!" e.g.
|
||||
|
||||
not (1 < 2);; - : bool = false
|
||||
*)
|
||||
|
||||
(*
|
||||
COMPARATORS
|
||||
|
||||
standard and, or comparisons e.g.
|
||||
|
||||
a && b, a || b
|
||||
|
||||
you can use >, <, but the comparator uses a
|
||||
single equal sign. e.g.
|
||||
|
||||
1. = 2.;; - : bool = false (* evaluates to false *)
|
||||
|
||||
-----------------------------------------------
|
||||
|
||||
NOT EQUALS
|
||||
|
||||
to check for inequality use "<>", e.g.
|
||||
|
||||
1. <> 2.;; - bool = true (* evaluates to true since 1. and 2. are not equal *)
|
||||
*)
|
||||
|
||||
(*
|
||||
STRING CONCATONATION
|
||||
|
||||
use the "^" (carrot operator) to concat strings e.g.
|
||||
*)
|
||||
"Braeden" ^ " " ^ "Sowinski"
|
||||
|
||||
(*
|
||||
FUNCTIONS
|
||||
|
||||
define a function square that takes in a
|
||||
parameter x and returns x * x
|
||||
*)
|
||||
let square x = x * x;;
|
||||
square 5;;
|
||||
|
||||
(* evaluates to 6 *)
|
||||
let x = 1 in x + 5;;
|
||||
|
||||
let add x y = x + y;;
|
||||
|
||||
(*
|
||||
arrows are right associative
|
||||
|
||||
name : input -> input -> return type
|
||||
val add : int -> int -> int = <fun>
|
||||
|
||||
so this can be translated to int -> (int -> int)
|
||||
|
||||
this means that every function essentially takes in 1 argument
|
||||
that then returns another functoin that takes in another argument
|
||||
*)
|
||||
|
||||
(* valid *)
|
||||
add 1 2;;
|
||||
|
||||
(* valid *)
|
||||
(add 1) 2;;
|
||||
|
||||
(* invalid *)
|
||||
(*add (1 2);;*)
|
||||
|
||||
(*
|
||||
Ocaml is functional and there are no loops
|
||||
such as for or while,
|
||||
|
||||
all variables are immutable
|
||||
*)
|
||||
|
||||
let x = 1;;
|
||||
let x = 2;;
|
||||
(*
|
||||
x = 3;; (* cannot reassign, this evaluates as a comparison
|
||||
therefore variables are immutable *)
|
||||
*)
|
||||
(*
|
||||
RECURSION
|
||||
|
||||
recursion is related to mathematical induction,
|
||||
you typically have a proposition, e.g. P, where we
|
||||
know P(1) is true, and we assume P(k) is true
|
||||
where we can proove that P(k + 1) is true
|
||||
|
||||
to declare a recursive function you need "rec"
|
||||
*)
|
||||
let rec factorial n = if n = 0 then 1 else n * factorial (n - 1);;
|
||||
let r = (factorial 5);;
|
||||
print_int r;;
|
||||
print_endline "";;
|
||||
|
||||
(*
|
||||
tail-recursive
|
||||
|
||||
a recursive function is tail-recursive if the recursive
|
||||
call is the last thing we do, for example, factorial is not
|
||||
tail-recursive, because we need to multiply n to the recursive call.
|
||||
|
||||
non tail-recursive functions are bad since there is potential to bloew
|
||||
through the stack.
|
||||
|
||||
lets consider factorial 3 = 3 * fact 2
|
||||
= 3 * (2 * fact 1)
|
||||
= 3 * (2 * (1 * fact 0))
|
||||
= 3 * (2 * 1)
|
||||
= 3 * 2
|
||||
= 6
|
||||
|
||||
we can see that this is not tail recursive as we need to store a value for
|
||||
each part of the iteration, we can solve this by rewriting the function a little
|
||||
using an accumulator
|
||||
*)
|
||||
let rec fact n acc = if n = 0 then acc else fact (n - 1) (n * acc);;
|
||||
|
||||
(* we can have primes, e.g. function f, and function f prime or f' *)
|
||||
|
||||
let factorial' n = fact n 1;;
|
||||
let r = (factorial 5);;
|
||||
print_int r;;
|
||||
print_endline "";;
|
||||
|
||||
let factorial' = fact 1;;
|
||||
|
||||
(*
|
||||
consider the tail-recursive version of factorial, fact'
|
||||
|
||||
the signature is fact' n acc
|
||||
|
||||
fact' 1 3 = fact' 3 2
|
||||
= fact' 6 1
|
||||
= fact' 6 0
|
||||
|
||||
as you can see, the stack would not grow
|
||||
|
||||
lets combine the functoins into a single one
|
||||
with nesting
|
||||
*)
|
||||
(* final tail-recursive version *)
|
||||
let fact n =
|
||||
let rec fact' acc i =
|
||||
if i = 0 then acc
|
||||
else fact' (i * acc) (i - 1)
|
||||
in
|
||||
fact' 1 n;; (* automatically sets the accumulator to 1 *)
|
||||
|
||||
let r = fact 5;;
|
||||
print_int r;;
|
||||
print_endline "";;
|
||||
|
||||
(* example of a documentation comment *)
|
||||
|
||||
(** [gcd a b] returns the greatest common divisor of [a] and [b]
|
||||
* Requires:[a > 0] and [b > 0]
|
||||
*)
|
||||
let rec gcd a b =
|
||||
if a mod b = 0 then b
|
||||
else gcd b (a mod b);;
|
||||
(*
|
||||
let r = gcd 12 18;;
|
||||
print_int r;;
|
||||
print_endline "";; *)
|
||||
|
||||
let rec fib n =
|
||||
if n = 0 then 0
|
||||
else if n = 1 then 1
|
||||
else fib (n - 1) + fib (n - 2);;
|
||||
|
||||
let r = fib 10;;
|
||||
print_int r;;
|
||||
print_endline "";;
|
||||
|
||||
(* tail-recursive version *)
|
||||
let rec fib n =
|
||||
let rec fib' i a b =
|
||||
if i = n then a
|
||||
else fib' (i + 1) b (a + b)
|
||||
in
|
||||
fib' 0 0 1;;
|
||||
|
||||
let r = fib 10;;
|
||||
print_int r;;
|
||||
print_endline "";;
|
||||
|
||||
(*
|
||||
MUTALLY-RECURSIVE FUNCTION
|
||||
*)
|
||||
let rec even n =
|
||||
if n = 0 then true
|
||||
else odd (n - 1)
|
||||
and odd n =
|
||||
if n = 0 then false
|
||||
else even (n - 1);;
|
||||
|
||||
(*
|
||||
useful stuff
|
||||
|
||||
float_of_int 4
|
||||
int_of_string "123"
|
||||
*)
|
||||
|
||||
let square_root x =
|
||||
let good_enough y = abs_float (x -. y *. y) < 0.00000000001 in
|
||||
let rec aux y =
|
||||
if good_enough y then y
|
||||
else aux (0.5 *. (y +. x /. y))
|
||||
in
|
||||
aux 1.;;
|
||||
|
||||
print_float (square_root 2.);;
|
||||
print_endline "";;
|
||||
|
||||
(*
|
||||
Consider this
|
||||
|
||||
create an exponential function
|
||||
where it calculates e^x
|
||||
|
||||
using recursion
|
||||
*)
|
||||
@@ -0,0 +1,41 @@
|
||||
(*
|
||||
ocamlc -o tinker tinker.ml
|
||||
|
||||
^^^ compile command
|
||||
*)
|
||||
|
||||
(* Comments are weird *)
|
||||
|
||||
(*
|
||||
concat takes to paramters a and b and concats them
|
||||
together while seperated by a space
|
||||
*)
|
||||
let concat a b = a ^ " " ^ b;;
|
||||
|
||||
(*
|
||||
describe maps the concat function to each element
|
||||
in the list to describe the element with "eat"
|
||||
*)
|
||||
let describe = List.map (fun f -> concat "eat" f);;
|
||||
|
||||
|
||||
let full_name = concat "Braeden" "Sowinski";;
|
||||
print_endline full_name;;
|
||||
|
||||
let gruit = ["apple"; "banana"; "grape"];;
|
||||
|
||||
(*
|
||||
takes in a list and iterates over elements
|
||||
to print_endline the element
|
||||
*)
|
||||
let print_list_string list =
|
||||
List.iter print_endline list;;
|
||||
|
||||
(*
|
||||
I think this acts like a main method,
|
||||
creates the describe list then iterates
|
||||
and passes to the print_list_string function
|
||||
*)
|
||||
let () =
|
||||
let eating = describe gruit in
|
||||
print_list_string eating;;
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link rel="Up" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Length</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Module <a href="type_Length.html">Length</a></h1>
|
||||
|
||||
<pre><span id="MODULELength"><span class="keyword">module</span> Length</span>: <code class="code">sig</code> <a href="Length.html">..</a> <code class="code">end</code></pre><div class="info module top">
|
||||
<div class="info-desc">
|
||||
<p>returns the number of elements in the list <code class="code">l</code> - non tail recursive</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr width="100%">
|
||||
|
||||
<pre><span id="VALlength"><span class="keyword">val</span> length</span> : <code class="type">'a list -> int</code></pre>
|
||||
<pre><span id="VALtest_length"><span class="keyword">val</span> test_length</span> : <code class="type">unit -> unit</code></pre>
|
||||
<pre><span id="VALlength_tr"><span class="keyword">val</span> length_tr</span> : <code class="type">'a list -> int</code></pre><div class="info ">
|
||||
<div class="info-desc">
|
||||
<p>returns the number of elements in the list <code class="code">l</code> - tail recursive</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pre><span id="VALtest_length_tr"><span class="keyword">val</span> test_length_tr</span> : <code class="type">unit -> unit</code></pre></body></html>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div class = "index-list">
|
||||
<ul class="indexlist">
|
||||
<li><a href="index_values.html">Index of values</a></li>
|
||||
<li><a href="index_modules.html">Index of modules</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<table class="indextable module-list">
|
||||
<tr><td class="module"><a href="Length.html">Length</a></td><td><div class="info">
|
||||
returns the number of elements in the list <code class="code">l</code> - non tail recursive
|
||||
</div>
|
||||
</td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of class attributes</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of class attributes</h1>
|
||||
<table>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of class types</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of class types</h1>
|
||||
<table>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of classes</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of classes</h1>
|
||||
<table>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of exceptions</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of exceptions</h1>
|
||||
<table>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of extensions</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of extensions</h1>
|
||||
<table>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of class methods</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of class methods</h1>
|
||||
<table>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of module types</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of module types</h1>
|
||||
<table>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of modules</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of modules</h1>
|
||||
<table>
|
||||
<tr><td align="left"><div>L</div></td></tr>
|
||||
<tr><td><a href="Length.html">Length</a> </td>
|
||||
<td><div class="info">
|
||||
returns the number of elements in the list <code class="code">l</code> - non tail recursive
|
||||
</div>
|
||||
</td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of types</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of types</h1>
|
||||
<table>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,31 @@
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Index of values</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar"> <a class="up" href="index.html" title="Index">Up</a>
|
||||
</div>
|
||||
<h1>Index of values</h1>
|
||||
<table>
|
||||
<tr><td align="left"><div>L</div></td></tr>
|
||||
<tr><td><a href="Length.html#VALlength">length</a> [<a href="Length.html">Length</a>]</td>
|
||||
<td></td></tr>
|
||||
<tr><td><a href="Length.html#VALlength_tr">length_tr</a> [<a href="Length.html">Length</a>]</td>
|
||||
<td><div class="info">
|
||||
returns the number of elements in the list <code class="code">l</code> - tail recursive
|
||||
</div>
|
||||
</td></tr>
|
||||
<tr><td align="left"><div>T</div></td></tr>
|
||||
<tr><td><a href="Length.html#VALtest_length">test_length</a> [<a href="Length.html">Length</a>]</td>
|
||||
<td></td></tr>
|
||||
<tr><td><a href="Length.html#VALtest_length_tr">test_length_tr</a> [<a href="Length.html">Length</a>]</td>
|
||||
<td></td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,43 @@
|
||||
.keyword { font-weight : bold ; color : Red }
|
||||
.keywordsign { color : #C04600 }
|
||||
.comment { color : Green }
|
||||
.constructor { color : Blue }
|
||||
.type { color : #5C6585 }
|
||||
.string { color : Maroon }
|
||||
.warning { color : Red ; font-weight : bold }
|
||||
.info { margin-left : 3em; margin-right: 3em }
|
||||
.param_info { margin-top: 4px; margin-left : 3em; margin-right : 3em }
|
||||
.code { color : #465F91 ; }
|
||||
.typetable { border-style : hidden }
|
||||
.paramstable { border-style : hidden ; padding: 5pt 5pt}
|
||||
tr { background-color : White }
|
||||
td.typefieldcomment { background-color : #FFFFFF ; font-size: smaller ;}
|
||||
div.sig_block {margin-left: 2em}
|
||||
*:target { background: yellow; }
|
||||
body {font: 13px sans-serif; color: black; text-align: left; padding: 5px; margin: 0}
|
||||
h1 { font-size : 20pt ; text-align: center; }
|
||||
h2 { font-size : 20pt ; text-align: center; }
|
||||
h3 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ;padding: 2px; }
|
||||
h4 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ;padding: 2px; }
|
||||
h5 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90EDFF ;padding: 2px; }
|
||||
h6 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90FDFF ;padding: 2px; }
|
||||
div.h7 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ; padding: 2px; }
|
||||
div.h8 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #E0FFFF ; padding: 2px; }
|
||||
div.h9 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #F0FFFF ; padding: 2px; }
|
||||
div.h10 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #FFFFFF ; padding: 2px; }
|
||||
a {color: #416DFF; text-decoration: none}
|
||||
a:hover {background-color: #ddd; text-decoration: underline}
|
||||
pre { margin-bottom: 4px; font-family: monospace; }
|
||||
pre.verbatim, pre.codepre { }
|
||||
.indextable {border: 1px #ddd solid; border-collapse: collapse}
|
||||
.indextable td, .indextable th {border: 1px #ddd solid; min-width: 80px}
|
||||
.indextable td.module {background-color: #eee ; padding-left: 2px; padding-right: 2px}
|
||||
.indextable td.module a {color: #4E6272; text-decoration: none; display: block; width: 100%}
|
||||
.indextable td.module a:hover {text-decoration: underline; background-color: transparent}
|
||||
.deprecated {color: #888; font-style: italic}
|
||||
.indextable tr td div.info { margin-left: 2px; margin-right: 2px }
|
||||
ul.indexlist { margin-left: 0; padding-left: 0;}
|
||||
ul.indexlist li { list-style-type: none ; margin-left: 0; padding-left: 0; }
|
||||
ul.info-attributes {list-style: none; margin: 0; padding: 0; }
|
||||
div.info > p:first-child { margin-top:0; }
|
||||
div.info-desc > p:first-child { margin-top:0; margin-bottom:0; }
|
||||
@@ -0,0 +1,11 @@
|
||||
<html><head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="Start" href="index.html">
|
||||
<link title="Index of values" rel=Appendix href="index_values.html">
|
||||
<link title="Index of modules" rel=Appendix href="index_modules.html">
|
||||
<link title="Length" rel="Chapter" href="Length.html"><title>Length</title>
|
||||
</head>
|
||||
<body>
|
||||
<code class="code"><span class="keyword">sig</span> <span class="keyword">end</span></code></body></html>
|
||||
@@ -0,0 +1,187 @@
|
||||
(*
|
||||
if everything is fine, test functions
|
||||
will return the unit value
|
||||
*)
|
||||
|
||||
(** [length l] returns the number of elements in the list [l]; non tail recursive *)
|
||||
let rec length l =
|
||||
match l with
|
||||
| [] -> 0
|
||||
| x :: xs -> 1 + length xs;;
|
||||
|
||||
(**/**)
|
||||
let test_length () =
|
||||
assert (length [] = 0);
|
||||
assert (length [2] = 1);
|
||||
assert (length [5; 7; 8;] = 3)
|
||||
(**/**)
|
||||
|
||||
(** [length_tr l] returns the number of elements in the list [l]; tail recursive *)
|
||||
let length_tr l =
|
||||
let rec lenth_tr' acc l =
|
||||
match l with
|
||||
| [] -> acc
|
||||
| _ :: xs -> lenth_tr' (acc + 1) xs
|
||||
in
|
||||
lenth_tr' 0 l;;
|
||||
|
||||
(**/**)
|
||||
let test_length_tr () =
|
||||
assert (length_tr [] = 0);
|
||||
assert (length_tr [2] = 1);
|
||||
assert (length_tr [5; 7; 8;] = 3)
|
||||
(**/**)
|
||||
|
||||
(** [reverse l] returns the reverse order of list [l]; non tail recursive *)
|
||||
let rec reverse l =
|
||||
match l with
|
||||
| [] -> []
|
||||
| x :: xs -> reverse xs @ [x];;
|
||||
|
||||
(**/**)
|
||||
let test_reverse () =
|
||||
assert (reverse [] = []);
|
||||
assert (reverse [1] = [1]);
|
||||
assert (reverse [1; 2] = [2; 1])
|
||||
(**/**)
|
||||
|
||||
(** [reverse_tr l] returns the reverse order of list [l]; tail recursive *)
|
||||
let reverse_tr l =
|
||||
let rec reverse_tr' acc l =
|
||||
match l with
|
||||
| [] -> acc
|
||||
| x :: xs -> reverse_tr' (x :: acc) xs
|
||||
in
|
||||
reverse_tr' [] l;;
|
||||
|
||||
(**/**)
|
||||
let test_reverse_tr () =
|
||||
assert (reverse_tr [] = []);
|
||||
assert (reverse_tr [1] = [1]);
|
||||
assert (reverse_tr [1; 2] = [2; 1])
|
||||
(**/**)
|
||||
|
||||
(* list.rev is a built in reverse function *)
|
||||
|
||||
(** [take n l] returns a list containing the first [n] elements of [l];
|
||||
* return [] if (n <= 0); return [l] if [l has fewer elements than [n]];
|
||||
* non tail recursive *)
|
||||
let rec take n l =
|
||||
if n <= 0 then []
|
||||
else
|
||||
match l with
|
||||
| [] -> []
|
||||
| x :: xs -> x :: take (n - 1) xs
|
||||
|
||||
(**/**)
|
||||
let test_take () =
|
||||
assert (take 0 [1; 2; 3;] = []);
|
||||
assert (take 3 [4; 5; 6; 7; 8; 9] = [4; 5; 6]);
|
||||
assert (take 5 [1; 2; 3] = [1; 2; 3])
|
||||
(**/**)
|
||||
|
||||
(** [take_tr n l] returns a list containing the first [n] elements of [l];
|
||||
* return [] if (n <= 0); return [l] if [l has fewer elements than [n]];
|
||||
* tail recursive *)
|
||||
let take_tr n l =
|
||||
let rec take_tr' acc n l =
|
||||
if n <= 0 then reverse_tr(acc)
|
||||
else
|
||||
match l with
|
||||
| [] -> acc
|
||||
| x :: xs -> x :: take_tr' (x :: acc) (n - 1) xs
|
||||
in
|
||||
take_tr' [] n l;;
|
||||
|
||||
(**/**)
|
||||
let test_take_tr () =
|
||||
assert (take_tr 0 [1; 2; 3;] = []);
|
||||
assert (take_tr 3 [4; 5; 6; 7; 8; 9] = [4; 5; 6]);
|
||||
assert (take_tr 5 [1; 2; 3] = [1; 2; 3])
|
||||
(**/**)
|
||||
|
||||
(** [every_other l] returns a list consisting of every other element of [l]
|
||||
* starting from the first element; non tail recursive *)
|
||||
let rec every_other l =
|
||||
match l with
|
||||
| x :: _ :: xs -> every_other xs
|
||||
| _ -> l;;
|
||||
|
||||
(**/**)
|
||||
let test_every_other () =
|
||||
assert (every_other [] = []);
|
||||
assert (every_other [1] = []);
|
||||
assert (every_other [1; 2] = [2]);
|
||||
assert (every_other [1; 2; 3] = [2]);
|
||||
assert (every_other [1; 2; 3; 4] = [2; 4])
|
||||
(**/**)
|
||||
|
||||
(** [every_other_tr l] returns a list consisting of every other element of [l]
|
||||
* starting from the first element; tail recursive *)
|
||||
let every_other_tr l =
|
||||
let rec every_other_tr' acc l =
|
||||
match l with
|
||||
| x :: _ :: xs -> every_other_tr' (x :: acc) xs
|
||||
| _ -> reverse_tr acc
|
||||
in
|
||||
every_other_tr' [] l;;
|
||||
|
||||
(**/**)
|
||||
let test_every_other_tr () =
|
||||
assert (every_other_tr [] = []);
|
||||
assert (every_other_tr [1] = []);
|
||||
assert (every_other_tr [1; 2] = [2]);
|
||||
assert (every_other_tr [1; 2; 3] = [2]);
|
||||
assert (every_other_tr [1; 2; 3; 4] = [2; 4])
|
||||
(**/**)
|
||||
|
||||
(** [sum l1 l2] returns a list consisting of the sum of corresponding integers
|
||||
* in [l1] and [l2]; non tail recursive *)
|
||||
let rec sum l1 l2 =
|
||||
match l1, l2 with (* this is a tuple of (l1, l2) *)
|
||||
| [], _ | _, [] -> [] (* if l1 is empty or l2 is empty, return empty *)
|
||||
| x1 :: xs1, x2 :: xs2 ->
|
||||
(x1 + x2) :: sum xs1 xs2;;
|
||||
|
||||
(**/**)
|
||||
let test_sum () =
|
||||
assert (sum [] [] = []);
|
||||
assert (sum [1] [] = []);
|
||||
assert (sum [] [1] = []);
|
||||
assert (sum [7] [8] = [15]);
|
||||
assert (sum [7; 3] [8; 8] = [15; 11]);
|
||||
assert (sum [7] [8; 8] = [15])
|
||||
(**/**)
|
||||
|
||||
(** [sum_tr l1 l2] returns a list consisting of the sum of corresponding integers
|
||||
* in [l1] and [l2]; tail recursive *)
|
||||
let sum_tr l1 l2 =
|
||||
let rec sum_tr' acc l1 l2 =
|
||||
match l1, l2 with
|
||||
| [], _ | _, [] -> reverse_tr acc
|
||||
| x1 :: xs1, x2 :: xs2 ->
|
||||
sum_tr' ((x1 + x2) :: acc) xs1 xs2
|
||||
in
|
||||
sum_tr' [] l1 l2;;
|
||||
|
||||
(**/**)
|
||||
let test_sum_tr () =
|
||||
assert (sum_tr [] [] = []);
|
||||
assert (sum_tr [1] [] = []);
|
||||
assert (sum_tr [] [1] = []);
|
||||
assert (sum_tr [7] [8] = [15]);
|
||||
assert (sum_tr [7; 3] [8; 8] = [15; 11]);
|
||||
assert (sum_tr [7] [8; 8] = [15])
|
||||
(**/**)
|
||||
|
||||
(** [count_change amt denoms] returns the number of ways of breaking up [amt]
|
||||
* into currencies with denominations specified by [denoms];
|
||||
* Require: elements of [denoms] must be positive *)
|
||||
let rec count_change amt denoms =
|
||||
if amt < 0 then 0
|
||||
else if amt = 0 then 1
|
||||
else
|
||||
match denoms with
|
||||
| [] -> 0
|
||||
| d :: ds ->
|
||||
count_change (amt - d) denoms + count_change amt ds;; (* use/not-use d *)
|
||||
@@ -0,0 +1,135 @@
|
||||
(*
|
||||
***** TUPLES *****
|
||||
has a fixed number of elements
|
||||
*)
|
||||
let x = (1, 2.1, "hello");;
|
||||
|
||||
(*
|
||||
this is also a tuple, but this tuple
|
||||
is a different type to the tuple above
|
||||
*)
|
||||
let y = (1, 2.1, "hello", "goodbye");;
|
||||
|
||||
(*
|
||||
function with tuple argument
|
||||
|
||||
accepts a tuple with 3 elements of int
|
||||
*)
|
||||
let add_tuple (x, y, z) = x + y + z;;
|
||||
|
||||
(*
|
||||
***** PATTERN MATCHING *****
|
||||
where x gets deconstructed into a, b, and c
|
||||
*)
|
||||
let (a, b, c) = x;;
|
||||
|
||||
a;;
|
||||
b;;
|
||||
c;;
|
||||
|
||||
(*
|
||||
***** LISTS *****
|
||||
|
||||
lists are semi-colon seperated values of the same type
|
||||
lists are a recursive data type
|
||||
*)
|
||||
let nums = [1; 2; 3];; (* this is a valid list *)
|
||||
|
||||
(*
|
||||
warning -
|
||||
this is valid syntax but this is a list with a single
|
||||
element that is a tuple of 3 ints
|
||||
*)
|
||||
let nums = [1, 2, 3];;
|
||||
(* results in - list : [(1, 2, 3)] *)
|
||||
|
||||
(*
|
||||
since lists are recursive data structures
|
||||
we can add elements to the front of the list
|
||||
as seen below
|
||||
|
||||
this operation is called cons
|
||||
*)
|
||||
2 :: (1 :: []);;
|
||||
2 :: 1 :: [];;
|
||||
|
||||
(*
|
||||
[1; 2; 3] === 1 :: 2 :: 3 :: [];;
|
||||
*)
|
||||
|
||||
(* list of lists *)
|
||||
[[1; 2]; [3; 4]];;
|
||||
|
||||
(* list concatonation *)
|
||||
[1; 2] @ [3; 4];;
|
||||
|
||||
[];;
|
||||
(*
|
||||
results in - : 'a list = []
|
||||
|
||||
where 'a means its a type variable
|
||||
since lists are generic
|
||||
*)
|
||||
|
||||
let l = [[1; 2]; [3]; []];;
|
||||
|
||||
(*
|
||||
pattern matching lists to extract 3
|
||||
pattern matching must be exhaustive
|
||||
*)
|
||||
let [_; [x]; _] = l;;
|
||||
|
||||
let data = [(1, 2, 'a'); (5, 3, 'b'); (4, 1, 'c'); (5, 0, 'd')];;
|
||||
let _ :: (_, _, x) :: _ = data;;
|
||||
x;;
|
||||
|
||||
(*
|
||||
recursive function
|
||||
with pattern matching to find
|
||||
length of list
|
||||
*)
|
||||
|
||||
(**
|
||||
* {length l} returns the number of elements
|
||||
* in the list {l} - non tail recursive
|
||||
*)
|
||||
let rec length l =
|
||||
match l with
|
||||
| [] -> 0
|
||||
| x :: xs -> 1 + length xs;;
|
||||
|
||||
(**
|
||||
* {length_tr l} returns the number of elements
|
||||
* in the list {l} - tail recursive
|
||||
*)
|
||||
let length_tr l =
|
||||
let rec aux acc l =
|
||||
match l with
|
||||
| [] -> acc
|
||||
| _ :: xs -> aux (acc + 1) xs
|
||||
in
|
||||
aux 0 l;;
|
||||
|
||||
(*
|
||||
GENERATE WEB DOCUMENTATION
|
||||
|
||||
mkdir html
|
||||
ocamldoc -html -d html main.ml
|
||||
|
||||
*)
|
||||
|
||||
(*
|
||||
there is no void in ocaml,
|
||||
everything has to return a value
|
||||
all expressions have a value;
|
||||
|
||||
if your function has no value to
|
||||
return, you still need to return something
|
||||
so return the unit value
|
||||
|
||||
example:
|
||||
printf is like a utility to print to the
|
||||
console but does not need to return any value
|
||||
so it returns the unit value
|
||||
*)
|
||||
Printf.printf "Hello, world\n";;
|
||||
@@ -0,0 +1,214 @@
|
||||
(* PARTIAL FUNCTIONS - because it does not return a value in
|
||||
some cases *)
|
||||
|
||||
let hd l =
|
||||
match l with
|
||||
| [] -> failwith "hd: empty list"
|
||||
| x:: _ -> x;;
|
||||
|
||||
let tl l =
|
||||
match l with
|
||||
| [] -> failwith "tl: empty list"
|
||||
| _ :: xs -> xs;;
|
||||
|
||||
(* associative list is a list of pairs *)
|
||||
let al = [("a123", 55); ("b456", 67)];;
|
||||
|
||||
(** [find k l] returns a value v from a key [k] in a list of pairs [l]
|
||||
* fails if not found
|
||||
*)
|
||||
let rec find k l =
|
||||
match l with
|
||||
| [] -> failwith "find: key not found"
|
||||
| (k', v') :: _ when k = k' -> v'
|
||||
| _ :: xs -> find k xs;;
|
||||
|
||||
(*
|
||||
best case is to have a TOTAL FUNCTION, always return a value
|
||||
this can be accomplished with an option type, that has two
|
||||
variants, either None or Some e.g. None;; Some 2;;
|
||||
*)
|
||||
|
||||
(** [find_opt k l] returns an optional value v from a key [k] in a list of pairs [l] *)
|
||||
let rec find_opt k l =
|
||||
match l with
|
||||
| [] -> None
|
||||
| (k', v') :: _ when k = k' -> Some v'
|
||||
| _ :: xs -> find_opt k xs;;
|
||||
|
||||
(*** HIGHER ORDER FUNCTIONS ***)
|
||||
|
||||
(** [insert x l] inserts element [x] into list [l]
|
||||
* Requires: [l] is in ascending order. *)
|
||||
let rec insert x l =
|
||||
match l with
|
||||
| [] -> [x]
|
||||
| y :: ys ->
|
||||
if x <= y then x :: l
|
||||
else y :: insert x ys;;
|
||||
|
||||
(* Note: the following insert is the same logically, just shorter *)
|
||||
(** [insert x l] inserts element [x] into list [l]
|
||||
* Requires: [l] is in ascending order. *)
|
||||
let rec insert x l =
|
||||
match l with
|
||||
| y :: ys when x > y -> y :: insert x ys
|
||||
| _ -> x :: l
|
||||
|
||||
(** [insertion_sort l] sorts list [l] in ascending order *)
|
||||
let rec insertion_sort l =
|
||||
match l with
|
||||
| [] -> []
|
||||
| x :: xs -> insert x (insertion_sort xs)
|
||||
|
||||
(*** ANONYMOUS FUNCTIONS ***)
|
||||
(* fun x -> x * x;; <-- syntax*)
|
||||
let f' x = x * x;;
|
||||
|
||||
(* these functions are equivalent *)
|
||||
let a = fun x y -> x + y;; (* func that takes two params *)
|
||||
let a' x = fun y -> x + y;; (* func taht takes 1 param and returns a func that takes 1 param *)
|
||||
|
||||
let s x = x * x;;
|
||||
(* f 2 + 3;; (* result: 7 *)
|
||||
f (2 + 3);; (* result: 25 *)
|
||||
f @@ 2 + 3;; (* result: 25 *) *)
|
||||
|
||||
let rec insertion_sort l =
|
||||
match l with
|
||||
| [] -> []
|
||||
| x :: xs -> insert x @@ insertion_sort xs;;
|
||||
|
||||
(* function is short form of "l = match l with ..." *)
|
||||
let rec insertion_sort = function
|
||||
| [] -> []
|
||||
| x :: xs -> insert x @@ insertion_sort xs;;
|
||||
|
||||
let inc x = x + 1;;
|
||||
let square x = x * x;;
|
||||
let add x y = x + y;;
|
||||
|
||||
square (inc 1);; (* r = 4 *)
|
||||
square @@ inc 1;; (* r = 4 *)
|
||||
1 |> inc |> square;; (* pipe operator - r = 4 or <|*)
|
||||
1 |> inc |> square |> add 2;; (* r = 6 *)
|
||||
|
||||
let flip f x y = f y x;;
|
||||
let sub x y = x - y;;
|
||||
flip sub 1 2;; (* flips two arguments, becomes sub 2 1 *)
|
||||
|
||||
(** [map f l] for each element in list [l] apply func [f]
|
||||
* return list of [l] with func [f] applied to elems *)
|
||||
let rec map f l =
|
||||
match l with
|
||||
| [] -> []
|
||||
| x :: xs -> f x :: map f xs;;
|
||||
|
||||
map (fun x -> x * x) [1; 2; 3; 4; 5; 6];;
|
||||
map int_of_string_opt ["1"; "2"; "3"; "z"];;
|
||||
|
||||
(** [filter f l] for each element in list [l] keep
|
||||
* element if it passes predicate func [f] *)
|
||||
let rec filter f l =
|
||||
match l with
|
||||
| [] -> []
|
||||
| x :: xs when f x -> x :: filter f xs
|
||||
| _ :: xs -> filter f xs;;
|
||||
|
||||
filter (fun x -> x mod 2 = 0) [1; 2; 3; 4; 5; 6; 7; 8; 9];;
|
||||
["a"; "1"; "2"] |> map int_of_string_opt |> filter (function | None -> false | Some _ -> true) (* filter out None *)
|
||||
(* list gets piped into the snd arg of map and result of map is piped to snd arg of filter *)
|
||||
(* pipes can go left also? <| *)
|
||||
|
||||
(** [take_while f l] returns the longest prefix of [l] each of its elements
|
||||
* satisfying [f] *)
|
||||
let take_while f l =
|
||||
let rec aux l acc =
|
||||
match l with
|
||||
| [] -> List.rev acc
|
||||
| x :: xs ->
|
||||
if f x then aux xs (x :: acc)
|
||||
else List.rev acc
|
||||
in
|
||||
aux l [];;
|
||||
|
||||
take_while (fun x -> x mod 2 = 0) [3; 2; 6; 6; 8];;
|
||||
take_while (fun x -> x mod 2 = 0) [2; 6; 7; 6; 8];;
|
||||
take_while (fun x -> x mod 2 = 0) [2; 6; 6; 8];;
|
||||
|
||||
(** [take_while f l] returns the longest prefix of [l] each of its elements
|
||||
* satisfying [f] *)
|
||||
let take_while f l =
|
||||
let rec aux l acc =
|
||||
match l with
|
||||
| x :: xs when f x -> aux xs (x :: acc)
|
||||
| _ -> List.rev acc
|
||||
in
|
||||
aux l [];;
|
||||
|
||||
take_while (fun x -> x mod 2 = 0) [3; 2; 6; 6; 8];;
|
||||
take_while (fun x -> x mod 2 = 0) [2; 6; 7; 6; 8];;
|
||||
take_while (fun x -> x mod 2 = 0) [2; 6; 6; 8];;
|
||||
|
||||
|
||||
|
||||
(*
|
||||
cmp x y < 0 x before y
|
||||
= 0 doesnt matter, x = y
|
||||
> 0 x after y
|
||||
*)
|
||||
|
||||
let rec insert' cmp x l =
|
||||
match l with
|
||||
| [] -> [x]
|
||||
| y :: ys ->
|
||||
if cmp x y <= 0 then x :: l
|
||||
else y :: insert' cmp x ys;;
|
||||
|
||||
let rec sort' cmp l =
|
||||
match l with
|
||||
| [] -> []
|
||||
| x :: xs ->
|
||||
insert' cmp x @@ sort' cmp xs;;
|
||||
|
||||
sort' Int.compare [3;2;7;6;8];;
|
||||
sort' (Fun.flip Int.compare) [3;2;7;6;8];;
|
||||
|
||||
(* with labeled arguments *)
|
||||
let rec insert'' ~cmp x l =
|
||||
match l with
|
||||
| [] -> [x]
|
||||
| y :: ys ->
|
||||
if cmp x y <= 0 then x :: l
|
||||
else y :: insert'' ~cmp x ys;;
|
||||
|
||||
let rec sort'' ~cmp l =
|
||||
match l with
|
||||
| [] -> []
|
||||
| x :: xs ->
|
||||
insert'' ~cmp x @@ sort'' ~cmp xs;;
|
||||
|
||||
(* labeled arguments can go anywhere *)
|
||||
sort'' [3;2;7;6;8] ~cmp:Int.compare;;
|
||||
sort'' ~cmp:(Fun.flip Int.compare) [3;2;7;6;8];;
|
||||
|
||||
(* process list from left to right *)
|
||||
(* fold_left -> (((acc $ x1) $ x2) $ x3) *)
|
||||
let rec fold_left f acc l =
|
||||
match l with
|
||||
| [] -> acc
|
||||
| x :: xs -> fold_left f (f acc x) xs;;
|
||||
|
||||
fold_left (fun acc x -> acc + x) 0 [3; 2; 7; 6; 8];;
|
||||
fold_left (+) 0 [3; 2; 7; 6; 8];;
|
||||
(+) 1 3;; (* makes + act like a function *)
|
||||
|
||||
(* process list from right to left *)
|
||||
(* fold_right -> (x1 $ (x2 $ (x3 $ acc))) *)
|
||||
let rec fold_right f l acc =
|
||||
match l with
|
||||
| [] -> acc
|
||||
| x :: xs -> f x (fold_right f xs acc);;
|
||||
|
||||
fold_left min max_int [3; 2; 7; 6; 8];;
|
||||
fold_right min [3; 2; 7; 6; 8] max_int;;
|
||||
@@ -0,0 +1,65 @@
|
||||
type 'a bstree = Leaf | Node of 'a * 'a bstree * 'a bstree;;
|
||||
|
||||
let rec bstree_size t =
|
||||
match t with
|
||||
| Leaf -> 0
|
||||
| Node (_, l, r) ->
|
||||
1 + bstree_size l + bstree_size r;;
|
||||
|
||||
let rec bstree_height t =
|
||||
match t with
|
||||
| Leaf -> 0
|
||||
| Node (_, l, r) ->
|
||||
1 + max (bstree_height l) (bstree_height r);;
|
||||
|
||||
let bstree_empty = Leaf;;
|
||||
|
||||
let bstree_is_empty t = t = Leaf;;
|
||||
|
||||
let rec bstree_insert ~cmp x t =
|
||||
match t with
|
||||
| Leaf -> Node (x, Leaf, Leaf)
|
||||
| Node (x', l, r) when cmp x x' < 0 ->
|
||||
Node (x', bstree_insert ~cmp x l, r)
|
||||
| Node (x', l, r) when cmp x x' > 0 ->
|
||||
Node (x', l, bstree_insert ~cmp x r)
|
||||
| _ -> t;;
|
||||
|
||||
let bstree_of_list ~cmp l =
|
||||
List.fold_left (Fun.flip (bstree_insert ~cmp)) Leaf l;;
|
||||
|
||||
let rec bstree_mem ~cmp x t =
|
||||
match t with
|
||||
| Leaf -> false
|
||||
| Node (x', l, _) when cmp x x' < 0 ->
|
||||
bstree_mem ~cmp x l
|
||||
| Node (x', _, r) when cmp x x' > 0 ->
|
||||
bstree_mem ~cmp x r
|
||||
| _ -> true;;
|
||||
|
||||
let rec bstree_largest t =
|
||||
match t with
|
||||
| Leaf -> failwith "bstree_largest: empty tree"
|
||||
| Node (x, _, Leaf) -> x
|
||||
| Node (_, _, r) -> bstree_largest r;;
|
||||
|
||||
let rec bstree_smallest t =
|
||||
match t with
|
||||
| Leaf -> failwith "bstree_smallest: empty tree"
|
||||
| Node (x, Leaf, _) -> x
|
||||
| Node (_, l, _) -> bstree_smallest l;;
|
||||
|
||||
let rec bstree_delete ~cmp x t =
|
||||
match t with
|
||||
| Leaf -> Leaf
|
||||
| Node (x', l, r) when cmp x x' < 0 ->
|
||||
Node (x', bstree_delete ~cmp x l, r)
|
||||
| Node (x', l, r) when cmp x x' > 0 ->
|
||||
Node (x', l, bstree_delete ~cmp x r)
|
||||
| Node (_, Leaf, Leaf) -> Leaf (* this does not need to be here, its a special case but ill leave it for clarity *)
|
||||
| Node (_, l, Leaf) -> l
|
||||
| Node (_, Leaf, r) -> r
|
||||
| Node (_, l, r) ->
|
||||
let succ = bstree_largest l in
|
||||
Node (succ, bstree_delete ~cmp succ l, r);;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
type bstree_size : 'a bstree -> int
|
||||
val bstree_height : 'a bstree -> int
|
||||
val bstree_empty : 'a bstree
|
||||
val bstree_is_empty : 'a bstree -> bool
|
||||
val bstree_insert : cmp:('a -> 'a -> int) -> 'a -> 'a bstree -> 'a bstree
|
||||
val bstree_of_list : cmp:('a -> 'a -> int) -> 'a list -> 'a bstree
|
||||
val bstree_mem : cmp:('a -> 'b -> int) -> 'a -> 'b bstree -> bool
|
||||
val bstree_largest : 'a bstree -> 'a
|
||||
val bstree_smallest : 'a bstree -> 'a
|
||||
val bstree_delete : cmp:('a -> 'a -> int) -> 'a -> 'a bstree -> 'a bstree
|
||||
@@ -0,0 +1,107 @@
|
||||
(* Some, None - Are called data/value constructors *)
|
||||
Some 1;; (* - : int option = Some 1 *)
|
||||
|
||||
None;; (* - : 'a option = None *)
|
||||
|
||||
(* OPTIONS are called type constructors, it takes a type *)
|
||||
(* 'a is a type variable, where 'a is some type such as int *)
|
||||
|
||||
type 'a option = None | Some of 'a;;
|
||||
|
||||
(*
|
||||
You can define any type you want, this type constructor starts
|
||||
with a lower case letter "direction" and the value constructor starts
|
||||
with uppercase "North", "East", ...
|
||||
|
||||
type constructors are not functions
|
||||
*)
|
||||
type direction = North | East | South | West;;
|
||||
|
||||
(* There are RESULT types *)
|
||||
Ok 1;;
|
||||
Error "hell";; (* albert's example is hell not my example *)
|
||||
|
||||
(*
|
||||
A result is a two type variable, this is the syntax for
|
||||
something that takes to type variables
|
||||
*)
|
||||
type ('a, 'b) result = Ok of 'a | Error of 'b;;
|
||||
|
||||
(1, 2);; (* type is - : int * int = (1, 2) *)
|
||||
(* (int, int) : (type * type) *)
|
||||
|
||||
(* we define an expresion that has a type of Int, and can be of type Add, Sub or Mul *)
|
||||
type expr =
|
||||
Int of int
|
||||
| Add of expr * expr
|
||||
| Sub of expr * expr
|
||||
| Mul of expr * expr;;
|
||||
|
||||
(* We then define an eval function, that takes in an eval,
|
||||
and recursively evaluates e1, e2 till they are just of
|
||||
type Int to then evaluate the addition, subtraction, etc. *)
|
||||
let rec eval = function
|
||||
| Int n -> n
|
||||
| Add (e1, e2) -> eval e1 + eval e2
|
||||
| Sub (e1, e2) -> eval e1 - eval e2
|
||||
| Mul (e1, e2) -> eval e1 * eval e2;;
|
||||
|
||||
let e = Mul(Add (Int 1, Int 2), Int 7);;
|
||||
eval e;;
|
||||
|
||||
(* lets apply the type variables and constructors to create a card type *)
|
||||
type suit = Club | Diamond | Heart | Spade;;
|
||||
type rank = Num of int | Jack | Queen | King | Ace;;
|
||||
type card = rank * suit;;
|
||||
|
||||
let compare_rank r1 r2 =
|
||||
match r1, r2 with
|
||||
| Num x, Num y -> Int.compare x y
|
||||
| Num _, _ -> -1
|
||||
| _, Num _ -> 1
|
||||
| _, _ -> Stdlib.compare r1 r2;;
|
||||
|
||||
let compare_suit s1 s2 = Stdlib.compare s1 s2;;
|
||||
|
||||
let compare_card (r1, s1) (r2, s2) =
|
||||
let c = compare_rank r1 r2 in
|
||||
if c = 0 then compare_suit s1 s2
|
||||
else c;;
|
||||
|
||||
let string_of_suit = function
|
||||
| Club -> "clubs"
|
||||
| Diamond -> "diamonds"
|
||||
| Heart -> "hearts"
|
||||
| Spade -> "spades";;
|
||||
|
||||
let string_of_rank = function
|
||||
| Num n -> string_of_int n
|
||||
| Jack -> "Jack"
|
||||
| Queen -> "Queen"
|
||||
| King -> "King"
|
||||
| Ace -> "Ace"
|
||||
|
||||
let string_of_card (r, s) =
|
||||
string_of_rank r ^ " of " ^ string_of_suit s;;
|
||||
|
||||
compare_card (King, Diamond) (Queen, Heart);;
|
||||
string_of_card (Queen, Heart);;
|
||||
|
||||
let all_suits = [Club; Diamond; Heart; Spade];;
|
||||
let all_ranks =
|
||||
(List.init 9 (fun x -> x + 2) |> List.map (fun x -> Num x)) @
|
||||
[Jack; Queen; King; Ace];;
|
||||
|
||||
let all_cards =
|
||||
List.fold_right (fun rank acc -> (
|
||||
List.fold_right (fun suit acc -> (rank, suit) :: acc) all_suits []
|
||||
) @ acc) all_ranks [];;
|
||||
|
||||
type 'a linked_list = Nil | Cons of 'a * 'a linked_list;;
|
||||
|
||||
let rec map_linked f = function
|
||||
| Nil -> Nil
|
||||
| Cons (x, l) -> Cons (f x, map_linked f l);;
|
||||
|
||||
Cons (1, Cons (2, Cons (3, Nil))) |> map_linked (fun x -> x * x);;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
"Resource: /home/flami/Projects/comp3958/lecture05/number_lines.ml": "n\239\025\\<\011\028#\000A>\249\204\182\170r"
|
||||
"Rule: ocaml dependencies ml (%=cat )": "\210V\221`\251\191B\198\232\184\146#\164\015\176,"
|
||||
"Rule: ocaml: cmx* & o* -> native (%=number_file_lines )": "R|\021U[G\226zs:\214\154\1910a\177"
|
||||
"Rule: ocaml: ml & cmi -> cmx & o (%=cat )": "\025\244\2354\235@{lBk\211\031$\237><"
|
||||
"Rule: ocaml: cmx* & o* -> native (%=number_lines )": "\180K\170\211^n:g\196\220\030 \233\127*\149"
|
||||
"Rule: ocaml: cmx* & o* -> native (%=echo )": "\196\206\211\186\185&f\154\217p\215\195\248p\1485"
|
||||
"Resource: /home/flami/Projects/comp3958/lecture05/echo.ml": "h\001\167\215xe\171\150p\151\004p>\004%\181"
|
||||
"Rule: ocaml dependencies ml (%=sum_integers )": "\207\140\220\182.\186\127\200\228\226\152\002dAJ\134"
|
||||
"Rule: ocaml dependencies ml (%=echo )": "\237\219\161\187\134\217\180\030\148\240\0166\176W\2222"
|
||||
"Resource: /home/flami/Projects/comp3958/lecture05/sum_integers.ml": "#b[\196\162u!\202\205~\135\239\025i\195\215"
|
||||
"Rule: ocaml: ml -> cmo & cmi (%=sum_integers )": "\015x\165\015\217\024\189(\143ud\232#\158Um"
|
||||
"Rule: ocaml: cmx* & o* -> native (%=sum_integers )": "q.\011\170\190\228da(\218\172\231\192\136\236+"
|
||||
"Rule: ocaml: ml -> cmo & cmi (%=cat )": "\248U3\213\015A\001\180 \023\180>\223}\142\188"
|
||||
"Rule: ocaml: ml -> cmo & cmi (%=number_file_lines )": "\218\210>\023\150\016u\174\235\179&6\234\147\248\016"
|
||||
"Rule: ocaml: ml & cmi -> cmx & o (%=echo )": "\1770\n\142p\235j\205HX\163\208\005\133n\t"
|
||||
"Rule: ocaml: ml & cmi -> cmx & o (%=sum_integers )": "\024\022\151\178THu\229\251\017\175G\230\179rD"
|
||||
"Rule: ocaml dependencies ml (%=number_lines )": "\023O8\158;\213,z\t`\236\204\250\168\140W"
|
||||
"Resource: /home/flami/Projects/comp3958/lecture05/number_file_lines.ml": ":\233\133ai\245 \000\199f8\022\140<\199\174"
|
||||
"Resource: /home/flami/Projects/comp3958/lecture05/cat.ml": "^\135\t\199Rr\210]\197\127HpY\r\147\170"
|
||||
"Rule: ocaml: ml -> cmo & cmi (%=echo )": "\224\\C\014\150\004=\191p\132*-\017jj\242"
|
||||
"Rule: ocaml dependencies ml (%=number_file_lines )": "\142\151\154\251\184\227\201\196\243\150\003\242\017\222\229X"
|
||||
"Rule: ocaml: ml & cmi -> cmx & o (%=number_lines )": "l\154\251\180\134\026\206s\139\030!A\155\t\198\161"
|
||||
"Rule: ocaml: ml -> cmo & cmi (%=number_lines )": "\029\1849 z\004\n\025\253\155]\017\244\252\141\129"
|
||||
"Rule: ocaml: cmx* & o* -> native (%=cat )": "j\019\018\218,\202\215\161 &5SE\134\223/"
|
||||
"Rule: ocaml: ml & cmi -> cmx & o (%=number_file_lines )": "|\132>\000@\222\195L,\1271\1424\141wJ"
|
||||
@@ -0,0 +1,12 @@
|
||||
### Starting build.
|
||||
# Target: /home/flami/.opam/default/bin/ocamlc.opt -config, tags: { }
|
||||
/home/flami/.opam/default/bin/ocamlc.opt -config
|
||||
# Target: number_lines.ml.depends, tags: { extension:ml, file:number_lines.ml, ocaml, ocamldep, quiet }
|
||||
/home/flami/.opam/default/bin/ocamldep.opt -modules number_lines.ml > number_lines.ml.depends
|
||||
# Target: number_lines.cmo, tags: { byte, compile, extension:cmo, extension:ml, file:number_lines.cmo, file:number_lines.ml, implem, ocaml, quiet }
|
||||
/home/flami/.opam/default/bin/ocamlc.opt -c -o number_lines.cmo number_lines.ml
|
||||
# Target: number_lines.cmx, tags: { compile, extension:cmx, extension:ml, file:number_lines.cmx, file:number_lines.ml, implem, native, ocaml, quiet }
|
||||
/home/flami/.opam/default/bin/ocamlopt.opt -c -o number_lines.cmx number_lines.ml
|
||||
# Target: number_lines.native, tags: { dont_link_with, extension:native, file:number_lines.native, link, native, ocaml, program, quiet }
|
||||
/home/flami/.opam/default/bin/ocamlopt.opt number_lines.cmx -o number_lines.native
|
||||
# Compilation successful.
|
||||
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
(* display content of file read via stdin *)
|
||||
let rec cat () =
|
||||
try
|
||||
let line = read_line () in
|
||||
print_endline line;
|
||||
cat()
|
||||
with
|
||||
| _ -> ();; (* EOF return unit *)
|
||||
|
||||
(* similar to main function *)
|
||||
let () =
|
||||
let rec aux () =
|
||||
try
|
||||
print_endline @@ read_line ();
|
||||
aux ()
|
||||
with
|
||||
| _ -> ()
|
||||
in
|
||||
aux()
|
||||
|
||||
(**** build and test ****)
|
||||
(*
|
||||
ocamlbuild cat.native
|
||||
./cat.native < filename
|
||||
*)
|
||||
@@ -0,0 +1 @@
|
||||
cat.ml:
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
let () =
|
||||
let len = Array.length Sys.argv - 1 in
|
||||
for i = 1 to len do
|
||||
Printf.printf (if i <> len then "%s " else "%s\n") Sys.argv.(i)
|
||||
done;;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
echo.ml: Array Printf Sys
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,16 @@
|
||||
let rec number acc ic =
|
||||
try
|
||||
Printf.printf "%5d| %s\n" acc @@ input_line ic;
|
||||
number (acc + 1) ic
|
||||
with
|
||||
| _ -> if ic <> stdin then close_in ic else ()
|
||||
|
||||
let () =
|
||||
if Array.length Sys.argv = 1 then
|
||||
number 1 stdin
|
||||
else
|
||||
try
|
||||
number 1 @@ open_in Sys.argv.(1)
|
||||
with
|
||||
| Sys_error s -> Printf.eprintf "%s\n" s;;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
number_file_lines.ml: Array Printf Sys
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
let () =
|
||||
let rec aux acc =
|
||||
try
|
||||
Printf.printf "%5d| %s\n" acc @@ read_line ();
|
||||
aux (acc + 1)
|
||||
with
|
||||
| _ -> ()
|
||||
in
|
||||
aux 1;;
|
||||
@@ -0,0 +1 @@
|
||||
number_lines.ml: Printf
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,12 @@
|
||||
let () =
|
||||
let rec aux sum =
|
||||
try
|
||||
aux @@ Scanf.scanf " %d" (fun x -> sum + x)
|
||||
with
|
||||
| Scanf.Scan_failure _ ->
|
||||
Scanf.scanf " %s" (fun _ -> ());
|
||||
aux sum
|
||||
| End_of_file -> sum
|
||||
in
|
||||
Printf.printf "%d\n" @@ aux 0;;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
sum_integers.ml: Printf Scanf
|
||||
Binary file not shown.
@@ -0,0 +1,26 @@
|
||||
(* display content of file read via stdin *)
|
||||
let rec cat () =
|
||||
try
|
||||
let line = read_line () in
|
||||
print_endline line;
|
||||
cat()
|
||||
with
|
||||
| _ -> ();; (* EOF return unit *)
|
||||
|
||||
(* similar to main function *)
|
||||
let () =
|
||||
let rec aux () =
|
||||
try
|
||||
print_endline @@ read_line ();
|
||||
aux ()
|
||||
with
|
||||
| _ -> ()
|
||||
in
|
||||
aux()
|
||||
(* cat() *)
|
||||
|
||||
(**** build and test ****)
|
||||
(*
|
||||
ocamlbuild cat.native
|
||||
./cat.native < filename
|
||||
*)
|
||||
@@ -0,0 +1,4 @@
|
||||
123 456
|
||||
-123 -456
|
||||
abc
|
||||
25
|
||||
@@ -0,0 +1,6 @@
|
||||
let () =
|
||||
let len = Array.length Sys.argv - 1 in
|
||||
for i = 1 to len do
|
||||
Printf.printf (if i <> len then "%s " else "%s\n") Sys.argv.(i)
|
||||
done;;
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
(**** RECORDS ****)
|
||||
type student = {id: string; name: string; gpa: float};;
|
||||
|
||||
let s1 = {id = "a12345678"; name = "homer simpson"; gpa = 25.5};;
|
||||
let make_student id name gpa = { id = id; name = name; gpa = gpa };;
|
||||
let s2 = make_student "a000000" "monty burns" 99.9;;
|
||||
|
||||
(* defining a function to return the name field of a record *)
|
||||
let name {id = id; name = name; gpa = gpa} = name;;
|
||||
let name {id; name; gpa} = name;;
|
||||
let name {name} = name;;
|
||||
let name s = s.name;;
|
||||
|
||||
name s2;;
|
||||
|
||||
type instructor = {id: string; name: string; salary: float};;
|
||||
let i1 = {id = "a777777"; name = "lisa simpson"; salary = 100000.};;
|
||||
|
||||
(* name cannot be applied to constructor because name was defined before instructor
|
||||
and it deferred from student *)
|
||||
(* name i1;; *)
|
||||
|
||||
let id x = x.id;;
|
||||
|
||||
(* id s1;; <-- this doesnt work because id infers from the latest defined, such as instructor *)
|
||||
id i1;;
|
||||
|
||||
type isntr = Instructor of {id: string; name: string; salary: float};;
|
||||
let i1 = Instructor {id = "a777777"; name = "lisa simpson"; salary = 100000.};;
|
||||
|
||||
let s1 = make_student "a123456678" "homer simpson" 25.5;;
|
||||
let s2 = s1;; (* s2 is its own student it just shares the same data *)
|
||||
let s2 = {s1 with id = "a22222222"; name = "bart simpson"} (* this allows us to copy data and modify selected data *)
|
||||
|
||||
(**** MUTABILITY - you can mark fields as mutable ****)
|
||||
type student = {id: string; name: string; mutable gpa: float};;
|
||||
let make_student id name gpa = { id = id; name = name; gpa = gpa };;
|
||||
let s1 = make_student "a123456678" "homer simpson" 25.5;;
|
||||
let s2 = s1;; (* refer to the same thing *)
|
||||
|
||||
s2;;
|
||||
|
||||
(* update field for s1 *)
|
||||
s1.gpa <- 15.5;
|
||||
|
||||
(* shows changes applied to s1 since s2 refers to the same data *)
|
||||
s2;;
|
||||
|
||||
(**** REFERENCES & DEREFEREMCES ****)
|
||||
let x = ref 1;;
|
||||
!x;; (* deref *)
|
||||
x := 2;; (* update val of references *)
|
||||
x;;
|
||||
!x;;
|
||||
|
||||
let y = x;;
|
||||
y;;
|
||||
x;;
|
||||
incr x;; (* y is the same as x (ref to int) so updating x also shows in y *)
|
||||
x;;
|
||||
y;;
|
||||
|
||||
let x = ref (Some 1);;
|
||||
let y = ref None;;
|
||||
(* val y : '_wek1 option ref = {contents = None} *)
|
||||
(* curremtly the contents of y are weakly polymorphic
|
||||
because it can be any type. the type inference cannot
|
||||
deduce the value of the optional *)
|
||||
y := Some 2;;
|
||||
y;;
|
||||
(* - : int option ref = {contents = Some 1} *)
|
||||
|
||||
(**** ARRAYS - arrays are mutable ****)
|
||||
[|1;2;3;3;4;5|];; (* arrays have vertical bars unlike lists *)
|
||||
let a = [|1;2;3|];;
|
||||
a.(0);; (* get first element *);;
|
||||
a.(1);;
|
||||
a.(2);;
|
||||
(* a.(3);; (* Invalid_argument excetption *) *)
|
||||
|
||||
a.(0) <- -1;;
|
||||
a;;
|
||||
|
||||
(**** FOR / WHILE LOOPS ****)
|
||||
(* for loops on arrays... yikes *)
|
||||
Array.length a;;
|
||||
for i = 0 to Array.length a - 1 do
|
||||
a.(i) <- 2 * a.(i)
|
||||
done;;
|
||||
|
||||
a;;
|
||||
|
||||
(* you can go in reverse also using downto *)
|
||||
for i = Array.length a - 1 downto 0 do
|
||||
a.(i) <- 2 * a.(i)
|
||||
done;;
|
||||
|
||||
(* while loops also... *)
|
||||
let i = ref 0;;
|
||||
while !i < Array.length a do
|
||||
(* adding semi-colon to end of expression means
|
||||
this is a garbage value, throw it away so we
|
||||
dont return unit() type early *)
|
||||
a.(!i) <- - !i;
|
||||
incr i
|
||||
done;;
|
||||
|
||||
a;;
|
||||
|
||||
(**** IGNORE ****)
|
||||
(* x will be 2 and the expression 1;
|
||||
is ignored because of the semi-colon *)
|
||||
let x = ignore 1; 2;;
|
||||
|
||||
(**** EXCEPTIONS ****)
|
||||
(* defining exceptions and rasing *)
|
||||
(* exception is a variant type and the
|
||||
number of variants can be extended *)
|
||||
(* exception Hell;; *)
|
||||
(* raise Hell;;
|
||||
Failure "hell";; *)
|
||||
|
||||
(* exceptions can have parameters *)
|
||||
exception Hell of int;;
|
||||
Hell 1;;
|
||||
Hell 2;;
|
||||
|
||||
(* List.hd [];; (* raises an exception *) *)
|
||||
|
||||
(* you can pattern match exceptions with try-with *)
|
||||
try
|
||||
List.hd []
|
||||
with
|
||||
| Failure _ -> -1;;
|
||||
|
||||
try
|
||||
List.hd []
|
||||
with
|
||||
| _ -> -1;;
|
||||
|
||||
|
||||
(**** IO ****)
|
||||
print_string "hello world\n";;
|
||||
print_endline "hello world";;
|
||||
print_int 123;;
|
||||
print_float 123.4;;
|
||||
print_newline ();;
|
||||
Printf.printf "%5d\n" 123;;
|
||||
Printf.printf "%05d %s\n" 123 "hello";;
|
||||
Printf.eprintf "%05d %s\n" 123 "hello";; (* print to standard error channel *)
|
||||
|
||||
let x = read_line ();;
|
||||
|
||||
(* read in int - add space at the front, it matches any amount of leading whitespace *)
|
||||
Scanf.scanf " %d" (fun x -> x)
|
||||
|
||||
(* open file *)
|
||||
(* open_in "filename";; *)
|
||||
let ic = open_in "output";;
|
||||
input_line ic;;
|
||||
@@ -0,0 +1,16 @@
|
||||
let rec number acc ic =
|
||||
try
|
||||
Printf.printf "%5d| %s\n" acc @@ input_line ic;
|
||||
number (acc + 1) ic
|
||||
with
|
||||
| _ -> if ic <> stdin then close_in ic else ()
|
||||
|
||||
let () =
|
||||
if Array.length Sys.argv = 1 then
|
||||
number 1 stdin
|
||||
else
|
||||
try
|
||||
number 1 @@ open_in Sys.argv.(1)
|
||||
with
|
||||
| Sys_error s -> Printf.eprintf "%s\n" s;;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
let () =
|
||||
let rec aux acc =
|
||||
try
|
||||
Printf.printf "%5d| %s\n" acc @@ read_line ();
|
||||
aux (acc + 1)
|
||||
with
|
||||
| _ -> ()
|
||||
in
|
||||
aux 1;;
|
||||
@@ -0,0 +1 @@
|
||||
hello world
|
||||
@@ -0,0 +1,12 @@
|
||||
(* we can impliment our own ref type *)
|
||||
type 'a ref = { mutable contents: 'a };;
|
||||
|
||||
(* reference and dereference implimentation *)
|
||||
let ref x = { contents = x };;
|
||||
let (!) r = r.contents;;
|
||||
|
||||
(* assign to a mutable field *)
|
||||
let (:=) r x = r.contents <- x;;
|
||||
|
||||
let incr r = r.contents <- r.contents + 1;;
|
||||
let decr r = r.contents <- r.contents - 1;;
|
||||
@@ -0,0 +1,12 @@
|
||||
let () =
|
||||
let rec aux sum =
|
||||
try
|
||||
aux @@ Scanf.scanf " %d" (fun x -> sum + x)
|
||||
with
|
||||
| Scanf.Scan_failure _ ->
|
||||
Scanf.scanf " %s" (fun _ -> ());
|
||||
aux sum
|
||||
| End_of_file -> sum
|
||||
in
|
||||
Printf.printf "%d\n" @@ aux 0;;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"Rule: ocaml dependencies ml (%=two_list_queue )": "\153s\252\225.\205\197\1597\030\142\254Q\213.\135"
|
||||
"Resource: /home/flami/Projects/comp3958/lecture06/two_list_queue.ml": "\174\189*\255(\166==\251\006\232\150\141\1714\130"
|
||||
"Rule: ocaml: ml -> cmo & cmi (%=two_list_queue )": "9\165\179\031F'#6\127\149\136<\242y\019t"
|
||||
@@ -0,0 +1,8 @@
|
||||
### Starting build.
|
||||
# Target: /home/flami/.opam/default/bin/ocamlc.opt -config, tags: { }
|
||||
/home/flami/.opam/default/bin/ocamlc.opt -config
|
||||
# Target: two_list_queue.ml.depends, tags: { extension:ml, file:two_list_queue.ml, ocaml, ocamldep, quiet }
|
||||
/home/flami/.opam/default/bin/ocamldep.opt -modules two_list_queue.ml > two_list_queue.ml.depends
|
||||
# Target: two_list_queue.cmo, tags: { byte, compile, extension:cmo, extension:ml, file:two_list_queue.cmo, file:two_list_queue.ml, implem, ocaml, quiet }
|
||||
/home/flami/.opam/default/bin/ocamlc.opt -c -o two_list_queue.cmo two_list_queue.ml
|
||||
# Compilation successful.
|
||||
@@ -0,0 +1,42 @@
|
||||
(* queue is empty iff the first list is empty *)
|
||||
type 'a t = 'a list * 'a list;;
|
||||
|
||||
exception Empty;;
|
||||
|
||||
let empty = ([], []);;
|
||||
|
||||
let is_empty (l, _) = l = [];;
|
||||
|
||||
let enqueue x (l1, l2) =
|
||||
match l1 with
|
||||
| [] -> [x], l2
|
||||
| _ -> (l1, x :: l2);;
|
||||
|
||||
let dequeue (l1, l2) =
|
||||
match l1 with
|
||||
| [] -> raise Empty
|
||||
| [_] -> (List.rev l2, [])
|
||||
| _ :: xs -> (xs, l2);;
|
||||
|
||||
let dequeue_opt q =
|
||||
try
|
||||
Some (dequeue q)
|
||||
with
|
||||
| Empty -> None;;
|
||||
|
||||
let front (l, _) =
|
||||
match l with
|
||||
| [] -> raise Empty
|
||||
| x :: _ -> x;;
|
||||
|
||||
let front_opt (l, _) =
|
||||
match l with
|
||||
| [] -> None
|
||||
| x :: _ -> Some x;;
|
||||
|
||||
let of_list l =
|
||||
List.fold_left (Fun.flip enqueue) empty l;;
|
||||
|
||||
let to_list (l1, l2) =
|
||||
l1 @ List.rev l2;;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
two_list_queue.ml: Fun List
|
||||
@@ -0,0 +1,63 @@
|
||||
type 'a t = Leaf | Node of 'a * 'a t * 'a t;;
|
||||
|
||||
let rec size t =
|
||||
match t with
|
||||
| Leaf -> 0
|
||||
| Node (_, l, r) ->
|
||||
1 + size l + size r;;
|
||||
|
||||
let rec height t =
|
||||
match t with
|
||||
| Leaf -> 0
|
||||
| Node (_, l, r) ->
|
||||
1 + max (height l) (height r);;
|
||||
|
||||
let empty = Leaf;;
|
||||
|
||||
let is_empty t = t = Leaf;;
|
||||
|
||||
let rec insert x t =
|
||||
match t with
|
||||
| Leaf -> Node (x, Leaf, Leaf)
|
||||
| Node (x', l, r) when x < x' ->
|
||||
Node (x', insert x l, r)
|
||||
| Node (x', l, r) when x > x' ->
|
||||
Node (x', l, insert x r)
|
||||
| _ -> t;;
|
||||
|
||||
let of_list l =
|
||||
List.fold_left (Fun.flip insert) Leaf l;;
|
||||
|
||||
let rec mem x t =
|
||||
match t with
|
||||
| Leaf -> false
|
||||
| Node (x', l, _) when x < x' ->
|
||||
mem x l
|
||||
| Node (x', _, r) when x > x' ->
|
||||
mem x r
|
||||
| _ -> true;;
|
||||
|
||||
let rec largest t =
|
||||
match t with
|
||||
| Leaf -> failwith "largest: empty tree"
|
||||
| Node (x, _, Leaf) -> x
|
||||
| Node (_, _, r) -> largest r;;
|
||||
|
||||
let rec smallest t =
|
||||
match t with
|
||||
| Leaf -> failwith "smallest: empty tree"
|
||||
| Node (x, Leaf, _) -> x
|
||||
| Node (_, l, _) -> smallest l;;
|
||||
|
||||
let rec delete x t =
|
||||
match t with
|
||||
| Leaf -> Leaf
|
||||
| Node (x', l, r) when x < x' ->
|
||||
Node (x', delete x l, r)
|
||||
| Node (x', l, r) when x > x' ->
|
||||
Node (x', l, delete x r)
|
||||
| Node (_, l, Leaf) -> l
|
||||
| Node (_, Leaf, r) -> r
|
||||
| Node (_, l, r) ->
|
||||
let succ = largest l in
|
||||
Node (succ, delete succ l, r);;
|
||||
@@ -0,0 +1,14 @@
|
||||
(* type 'a t = Leaf | Node of 'a * 'a t * 'a t *)
|
||||
|
||||
type 'a t (* for abstract data type *)
|
||||
|
||||
val size : 'a t -> int
|
||||
val height : 'a t -> int
|
||||
val empty : 'a t
|
||||
val is_empty : 'a t -> bool
|
||||
val insert : 'a -> 'a t -> 'a t
|
||||
val of_list : 'a list -> 'a t
|
||||
val mem : 'a -> 'a t -> bool
|
||||
val largest : 'a t -> 'a
|
||||
val smallest : 'a t -> 'a
|
||||
val delete : 'a -> 'a t -> 'a t
|
||||
@@ -0,0 +1,68 @@
|
||||
(* dont do this *)
|
||||
|
||||
|
||||
module Bstree = struct
|
||||
type 'a t = Leaf | Node of 'a * 'a t * 'a t;;
|
||||
|
||||
let rec size t =
|
||||
match t with
|
||||
| Leaf -> 0
|
||||
| Node (_, l, r) ->
|
||||
1 + size l + size r;;
|
||||
|
||||
let rec height t =
|
||||
match t with
|
||||
| Leaf -> 0
|
||||
| Node (_, l, r) ->
|
||||
1 + max (height l) (height r);;
|
||||
|
||||
let empty = Leaf;;
|
||||
|
||||
let is_empty t = t = Leaf;;
|
||||
|
||||
let rec insert x t =
|
||||
match t with
|
||||
| Leaf -> Node (x, Leaf, Leaf)
|
||||
| Node (x', l, r) when x < x' ->
|
||||
Node (x', insert x l, r)
|
||||
| Node (x', l, r) when x > x' ->
|
||||
Node (x', l, insert x r)
|
||||
| _ -> t;;
|
||||
|
||||
let of_list l =
|
||||
List.fold_left (Fun.flip insert) Leaf l;;
|
||||
|
||||
let rec mem x t =
|
||||
match t with
|
||||
| Leaf -> false
|
||||
| Node (x', l, _) when x < x' ->
|
||||
mem x l
|
||||
| Node (x', _, r) when x > x' ->
|
||||
mem x r
|
||||
| _ -> true;;
|
||||
|
||||
let rec largest t =
|
||||
match t with
|
||||
| Leaf -> failwith "largest: empty tree"
|
||||
| Node (x, _, Leaf) -> x
|
||||
| Node (_, _, r) -> largest r;;
|
||||
|
||||
let rec smallest t =
|
||||
match t with
|
||||
| Leaf -> failwith "smallest: empty tree"
|
||||
| Node (x, Leaf, _) -> x
|
||||
| Node (_, l, _) -> smallest l;;
|
||||
|
||||
let rec delete x t =
|
||||
match t with
|
||||
| Leaf -> Leaf
|
||||
| Node (x', l, r) when x < x' ->
|
||||
Node (x', delete x l, r)
|
||||
| Node (x', l, r) when x > x' ->
|
||||
Node (x', l, delete x r)
|
||||
| Node (_, l, Leaf) -> l
|
||||
| Node (_, Leaf, r) -> r
|
||||
| Node (_, l, r) ->
|
||||
let succ = largest l in
|
||||
Node (succ, delete succ l, r);;
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
"Rule: ocaml dependencies mli (%=bstree )": "!\134$\216+23\213\196T\181K\021\128\195\018"
|
||||
"Resource: /home/flami/Projects/comp3958/lecture06/functor/bstree.mli": "\194\172\208\246\172^Y\171\1563@\144\158H\027l"
|
||||
"Rule: ocaml: ml & cmi -> cmo (%=bstree )": "\172\028\140\193\160\2525\162\225\231@cE\2307\244"
|
||||
"Resource: /home/flami/Projects/comp3958/lecture06/functor/bstree.ml": "\228\211>\161\t\1291\180\144c_ \189\147\236x"
|
||||
"Rule: ocaml: mli -> cmi (%=bstree )": "\225aH6\244\021+9l\172\247\209 d\183\159"
|
||||
"Rule: ocaml dependencies ml (%=bstree )": "\031$\199\007@\208\227\1694l\138\193r\227\203\171"
|
||||
@@ -0,0 +1,12 @@
|
||||
### Starting build.
|
||||
# Target: /home/flami/.opam/default/bin/ocamlc.opt -config, tags: { }
|
||||
/home/flami/.opam/default/bin/ocamlc.opt -config
|
||||
# Target: bstree.mli.depends, tags: { extension:mli, file:bstree.mli, ocaml, ocamldep, quiet }
|
||||
/home/flami/.opam/default/bin/ocamldep.opt -modules bstree.mli > bstree.mli.depends # cached
|
||||
# Target: bstree.cmi, tags: { byte, compile, extension:mli, file:bstree.mli, interf, ocaml, quiet }
|
||||
/home/flami/.opam/default/bin/ocamlc.opt -c -o bstree.cmi bstree.mli # cached
|
||||
# Target: bstree.ml.depends, tags: { extension:ml, file:bstree.ml, ocaml, ocamldep, quiet }
|
||||
/home/flami/.opam/default/bin/ocamldep.opt -modules bstree.ml > bstree.ml.depends
|
||||
# Target: bstree.cmo, tags: { byte, compile, extension:cmo, extension:ml, file:bstree.cmo, file:bstree.ml, implem, ocaml, quiet }
|
||||
/home/flami/.opam/default/bin/ocamlc.opt -c -o bstree.cmo bstree.ml
|
||||
# Compilation successful.
|
||||
@@ -0,0 +1,86 @@
|
||||
module type OrderedType = sig
|
||||
type t
|
||||
val compare : t -> t -> int
|
||||
end
|
||||
|
||||
module type S = sig
|
||||
type elt
|
||||
type t
|
||||
|
||||
val size : t -> int
|
||||
val height : t -> int
|
||||
val empty : t
|
||||
val is_empty : t -> bool
|
||||
val insert : elt -> t -> t
|
||||
val of_list : elt list -> t
|
||||
val mem : elt -> t -> bool
|
||||
val delete : elt -> t -> t
|
||||
end
|
||||
|
||||
module Make(Ord : OrderedType) = struct
|
||||
type elt = Ord.t;;
|
||||
type t = L | N of elt * t * t;;
|
||||
|
||||
let rec size t =
|
||||
match t with
|
||||
| L -> 0
|
||||
| N (_, l, r) ->
|
||||
1 + size l + size r;;
|
||||
|
||||
let rec height t =
|
||||
match t with
|
||||
| L -> 0
|
||||
| N (_, l, r) ->
|
||||
1 + max (height l) (height r);;
|
||||
|
||||
let empty = L;;
|
||||
|
||||
let is_empty t = t = L;;
|
||||
|
||||
let rec insert x t =
|
||||
match t with
|
||||
| L -> N (x, L, L)
|
||||
| N (x', l, r) when Ord.compare x x' < 0 ->
|
||||
N (x', insert x l, r)
|
||||
| N (x', l, r) when Ord.compare x x' > 0 ->
|
||||
N (x', l, insert x r)
|
||||
| _ -> t;;
|
||||
|
||||
let of_list l =
|
||||
List.fold_left (Fun.flip insert) L l;;
|
||||
|
||||
let rec mem x t =
|
||||
match t with
|
||||
| L -> false
|
||||
| N (x', l, _) when Ord.compare x x' < 0 ->
|
||||
mem x l
|
||||
| N (x', _, r) when Ord.compare x x' > 0 ->
|
||||
mem x r
|
||||
| _ -> true;;
|
||||
|
||||
let rec largest t =
|
||||
match t with
|
||||
| L -> failwith "largest: empty tree"
|
||||
| N (x, _, L) -> x
|
||||
| N (_, _, r) -> largest r;;
|
||||
|
||||
let rec smallest t =
|
||||
match t with
|
||||
| L -> failwith "smallest: empty tree"
|
||||
| N (x, L, _) -> x
|
||||
| N (_, l, _) -> smallest l;;
|
||||
|
||||
let rec delete x t =
|
||||
match t with
|
||||
| L -> L
|
||||
| N (x', l, r) when Ord.compare x x' < 0 ->
|
||||
N (x', delete x l, r)
|
||||
| N (x', l, r) when Ord.compare x x' > 0 ->
|
||||
N (x', l, delete x r)
|
||||
| N (_, L, L) -> L (* this does not need to be here, its a special case but ill leave it for clarity *)
|
||||
| N (_, l, L) -> l
|
||||
| N (_, L, r) -> r
|
||||
| N (_, l, r) ->
|
||||
let succ = largest l in
|
||||
N (succ, delete succ l, r);;
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
bstree.ml: Fun List
|
||||
@@ -0,0 +1,20 @@
|
||||
module type OrderedType = sig
|
||||
type t
|
||||
val compare : t -> t -> int
|
||||
end
|
||||
|
||||
module type S = sig
|
||||
type elt
|
||||
type t
|
||||
|
||||
val size : t -> int
|
||||
val height : t -> int
|
||||
val empty : t
|
||||
val is_empty : t -> bool
|
||||
val insert : elt -> t -> t
|
||||
val of_list : elt list -> t
|
||||
val mem : elt -> t -> bool
|
||||
val delete : elt -> t -> t
|
||||
end
|
||||
|
||||
module Make(Ord: OrderedType) : S with type elt = Ord.t
|
||||
@@ -0,0 +1 @@
|
||||
bstree.mli:
|
||||
@@ -0,0 +1,86 @@
|
||||
module type OrderedType = sig
|
||||
type t
|
||||
val compare : t -> t -> int
|
||||
end
|
||||
|
||||
module type S = sig
|
||||
type elt
|
||||
type t
|
||||
|
||||
val size : t -> int
|
||||
val height : t -> int
|
||||
val empty : t
|
||||
val is_empty : t -> bool
|
||||
val insert : elt -> t -> t
|
||||
val of_list : elt list -> t
|
||||
val mem : elt -> t -> bool
|
||||
val delete : elt -> t -> t
|
||||
end
|
||||
|
||||
module Make(Ord : OrderedType) = struct
|
||||
type elt = Ord.t;;
|
||||
type t = L | N of elt * t * t;;
|
||||
|
||||
let rec size t =
|
||||
match t with
|
||||
| L -> 0
|
||||
| N (_, l, r) ->
|
||||
1 + size l + size r;;
|
||||
|
||||
let rec height t =
|
||||
match t with
|
||||
| L -> 0
|
||||
| N (_, l, r) ->
|
||||
1 + max (height l) (height r);;
|
||||
|
||||
let empty = L;;
|
||||
|
||||
let is_empty t = t = L;;
|
||||
|
||||
let rec insert x t =
|
||||
match t with
|
||||
| L -> N (x, L, L)
|
||||
| N (x', l, r) when Ord.compare x x' < 0 ->
|
||||
N (x', insert x l, r)
|
||||
| N (x', l, r) when Ord.compare x x' > 0 ->
|
||||
N (x', l, insert x r)
|
||||
| _ -> t;;
|
||||
|
||||
let of_list l =
|
||||
List.fold_left (Fun.flip insert) L l;;
|
||||
|
||||
let rec mem x t =
|
||||
match t with
|
||||
| L -> false
|
||||
| N (x', l, _) when Ord.compare x x' < 0 ->
|
||||
mem x l
|
||||
| N (x', _, r) when Ord.compare x x' > 0 ->
|
||||
mem x r
|
||||
| _ -> true;;
|
||||
|
||||
let rec largest t =
|
||||
match t with
|
||||
| L -> failwith "largest: empty tree"
|
||||
| N (x, _, L) -> x
|
||||
| N (_, _, r) -> largest r;;
|
||||
|
||||
let rec smallest t =
|
||||
match t with
|
||||
| L -> failwith "smallest: empty tree"
|
||||
| N (x, L, _) -> x
|
||||
| N (_, l, _) -> smallest l;;
|
||||
|
||||
let rec delete x t =
|
||||
match t with
|
||||
| L -> L
|
||||
| N (x', l, r) when Ord.compare x x' < 0 ->
|
||||
N (x', delete x l, r)
|
||||
| N (x', l, r) when Ord.compare x x' > 0 ->
|
||||
N (x', l, delete x r)
|
||||
| N (_, L, L) -> L (* this does not need to be here, its a special case but ill leave it for clarity *)
|
||||
| N (_, l, L) -> l
|
||||
| N (_, L, r) -> r
|
||||
| N (_, l, r) ->
|
||||
let succ = largest l in
|
||||
N (succ, delete succ l, r);;
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
module type OrderedType = sig
|
||||
type t
|
||||
val compare : t -> t -> int
|
||||
end
|
||||
|
||||
module type S = sig
|
||||
type elt
|
||||
type t
|
||||
|
||||
val size : t -> int
|
||||
val height : t -> int
|
||||
val empty : t
|
||||
val is_empty : t -> bool
|
||||
val insert : elt -> t -> t
|
||||
val of_list : elt list -> t
|
||||
val mem : elt -> t -> bool
|
||||
val delete : elt -> t -> t
|
||||
end
|
||||
|
||||
module Make(Ord: OrderedType) : S with type elt = Ord.t
|
||||
Whitespace-only changes.
@@ -0,0 +1,8 @@
|
||||
module / struct
|
||||
module type / sig / interface
|
||||
|
||||
open M
|
||||
let opem M in ..
|
||||
M.(...)
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
type 'a t = 'a list;;
|
||||
|
||||
exception Empty
|
||||
|
||||
let empty = [];;
|
||||
|
||||
let is_empty q = q = [];;
|
||||
|
||||
let enqueue x q = q @ [x];;
|
||||
|
||||
let dequeue q =
|
||||
match q with
|
||||
| [] -> raise Empty
|
||||
| _ :: xs -> xs;;
|
||||
|
||||
let dequeue_opt q =
|
||||
match q with
|
||||
| [] -> None
|
||||
| _ :: xs -> Some xs;;
|
||||
|
||||
let front q =
|
||||
match q with
|
||||
| [] -> raise Empty
|
||||
| x :: _ -> x;;
|
||||
|
||||
let front_opt q =
|
||||
match q with
|
||||
| [] -> None
|
||||
| x :: _ -> Some x;;
|
||||
|
||||
let length q =
|
||||
List.length q;;
|
||||
|
||||
let of_list l = l;;
|
||||
|
||||
let to_list q = q;;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
(* queue is empty iff the first list is empty *)
|
||||
type 'a t = 'a list * 'a list;;
|
||||
|
||||
exception Empty;;
|
||||
|
||||
let empty = ([], []);;
|
||||
|
||||
let is_empty (l, _) = l = [];;
|
||||
|
||||
let enqueue x (l1, l2) =
|
||||
match l1 with
|
||||
| [] -> [x], l2
|
||||
| _ -> (l1, x :: l2);;
|
||||
|
||||
let dequeue (l1, l2) =
|
||||
match l1 with
|
||||
| [] -> raise Empty
|
||||
| [_] -> (List.rev l2, [])
|
||||
| _ :: xs -> (xs, l2);;
|
||||
|
||||
let dequeue_opt q =
|
||||
try
|
||||
Some (dequeue q)
|
||||
with
|
||||
| Empty -> None;;
|
||||
|
||||
let front (l, _) =
|
||||
match l with
|
||||
| [] -> raise Empty
|
||||
| x :: _ -> x;;
|
||||
|
||||
let front_opt (l, _) =
|
||||
match l with
|
||||
| [] -> None
|
||||
| x :: _ -> Some x;;
|
||||
|
||||
let of_list l =
|
||||
List.fold_left (Fun.flip enqueue) empty l;;
|
||||
|
||||
let to_list (l1, l2) =
|
||||
l1 @ List.rev l2;;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
(* bstree with records *)
|
||||
type 'a t = L | N of {v: 'a; l: 'a t; r: 'a t};;
|
||||
@@ -0,0 +1,7 @@
|
||||
let counter =
|
||||
let c = ref 0 in
|
||||
(fun () -> incr c; !c);;
|
||||
|
||||
let make_counter init =
|
||||
let c = ref init in
|
||||
(fun () -> let x = !c in incr c; x);;
|
||||
@@ -0,0 +1,12 @@
|
||||
module F = Map.Make(String)
|
||||
|
||||
let rec count map =
|
||||
let word = Scanf.scanf " %s" (fun w -> w) in
|
||||
if word = "" then map
|
||||
else count (F.update word (function
|
||||
| None -> Some 1
|
||||
| Some n -> Some (n + 1))
|
||||
map);;
|
||||
|
||||
let () =
|
||||
List.iter (fun (s, n) -> Printf.printf "%s: %d\n" s n) @@ count F.empty;;
|
||||
@@ -0,0 +1,46 @@
|
||||
(** rank of node = shortest distance to a leaf (empty node)
|
||||
* hence, rank of node = 1 + min(rnak of left, rank of right)
|
||||
* leftist tree has 2 properties:
|
||||
* For ever node
|
||||
* * leftist: rnak(left) >= rank(right)
|
||||
* * min-heap: value(parent) <= value(node)
|
||||
*)
|
||||
|
||||
type 'a t = L | N of int * 'a * 'a t * 'a t;;
|
||||
|
||||
exception Empty;;
|
||||
|
||||
let rank = function
|
||||
| L -> 0
|
||||
| N (rk, _, _, _) -> rk;;
|
||||
|
||||
let empty = L;;
|
||||
|
||||
let is_empty t = t = L;;
|
||||
|
||||
let rec merge t1 t2 =
|
||||
match t1, t2 with
|
||||
| t, L | L, t -> t
|
||||
| N (_, x1, _, _), N (_, x2, _, _) when x2 < x1 ->
|
||||
merge t2 t1
|
||||
| N (_, x, l, r), t ->
|
||||
let t' = merge r t in
|
||||
if rank t' > rank l then N (1 + rank l, x, t', l)
|
||||
else N (1 + rank t', x, l, t');;
|
||||
|
||||
let insert x t =
|
||||
merge t (N (1, x, L, L));;
|
||||
|
||||
let of_list l = List.fold_left (Fun.flip insert) L l;;
|
||||
|
||||
let get_min = function
|
||||
| L -> raise Empty
|
||||
| N (_, x, _, _) -> x;;
|
||||
|
||||
let delete_min = function
|
||||
| L -> L
|
||||
| N (_, _, l, r) -> merge l r;;
|
||||
|
||||
let rec to_list t =
|
||||
if is_empty t then []
|
||||
else get_min t :: to_list (delete_min t);;
|
||||
@@ -0,0 +1,47 @@
|
||||
(*
|
||||
- a module can contain other modules as well as module type definitions
|
||||
- a module type/sig (signature) can not contain modules but can contain other sigs
|
||||
- for a .ml/.mli pair,
|
||||
* anything not specified in .mli file is hidden
|
||||
* everything specified in the .mli file must be defined in the .ml file
|
||||
*)
|
||||
|
||||
module M = struct
|
||||
let f x = 2 * x
|
||||
end;;
|
||||
|
||||
module type S = module type of M;;
|
||||
|
||||
module M = struct
|
||||
let f x = 2 * x;;
|
||||
let g x = 3 * x;;
|
||||
module N = struct
|
||||
type t = int
|
||||
end
|
||||
end;;
|
||||
|
||||
(* S signature is the same as M if loaded in utop *)
|
||||
module type S = module type of M;;
|
||||
|
||||
(***** EXTENDED MODULES *****)
|
||||
|
||||
(* lets extend List module *)
|
||||
module ListExt = struct
|
||||
include List;; (* include module to extend *)
|
||||
let to_array l = Array.of_list l;;
|
||||
end;;
|
||||
|
||||
ListExt.to_array [3;2;7;6;8];;
|
||||
|
||||
module F = Map.Make(String);;
|
||||
|
||||
(* returns abstract type *)
|
||||
let m = F.empty |> F.add "hello" 1 |> F.add "hello" 2;;
|
||||
F.to_list m;;
|
||||
|
||||
let incr key m =
|
||||
F.update key (function | None -> Some 1 | Some x -> Some (x + 1))
|
||||
m;;
|
||||
|
||||
let m = incr "hello" m;;
|
||||
let m = incr "world" m;;
|
||||
@@ -0,0 +1,16 @@
|
||||
let isqrt n = n |> float_of_int |> sqrt |> int_of_float;;
|
||||
|
||||
let sieve n =
|
||||
let is_prime = Array.make n true in
|
||||
for i = 2 to isqrt n do
|
||||
if is_prime.(i) then
|
||||
let j = ref i in
|
||||
while i * !j < n do
|
||||
is_prime.(i * !j) <- false;
|
||||
incr j
|
||||
done
|
||||
done;
|
||||
is_prime.(0) <- false;
|
||||
is_prime.(1) <- false;
|
||||
is_prime |> Array.to_list |> List.mapi (fun i b -> (i, b)) |>
|
||||
List.filter_map (fun (i, b) -> if b then Some i else None);;
|
||||
Reference in new issue
Block a user