OCaml

OCaml官网 Ocaml教程

安装OCaml

1
2
# Homebrew
$ brew install opam

然后安装OCaml编译器

1
2
3
4
5
6
7
# environment setup
$ opam init
$ eval `opam env`

# install given version of the compiler
$ opam switch create 4.11.1
$ eval `opam env`

然后OCaml就能够运行了,在终端输入:

1
2
3
4
5
$ which ocaml
/Users/frank/.opam/4.11.1/bin/ocaml

$ ocaml -version
The OCaml toplevel, version 4.11.1

1. OCaml Top-level

1.1 Types and Values

1
2
42;;
- : int = 42

Dissect:

Reading right to left:

42 is the value

int is the type of the value

Value don’t have a name, hence use the symbol -

Bind the value with a let func

1
2
let x = 42;;
val x : int = 42

Here the value 42 is bound with name, so use val here

1.2 Functions

A function can be defined like:

1
2
let increment x = x + 1;; 
val increment : int -> int = <fun>

increment is the identifier to which the value was bound

int -> int is the type of the value, Take a int as input –> retun a int as output

<fun> is a placeholder, <fun> itself is not a value, just indicates an unprintable function value.

Call a func

1
2
3
4
increment 0 ;;
- : int = 1
increment (increment 5)
- : int = 7

1.3 Loading code in toplevel

Load the code in the toplevel with #use.

1
#use "mycode.ml";;

2. Compiling OCaml

Manually:

1
2
3
4
5
$ mkdir hello-world
$ code hello-world
$ ocamlc -o hello.byte hello.ml
$ ./hello.byte
$ rm hello.byte hello.cmi hello.cmo //clean up

Ocaml do not need to have main func like java…

Dune:

Create a file named dune

1
2
(executable
(name hello))

EX: for file hello.ml

1
2
3
4
$ dune build hello.exe
$ dune exec ./hello.exe
# Hello world!
$ dune clean

3. Expressions

3.1 Primitive Types and Values

Types:

Integers, floating-point numbers, characters, strings, and booleans.

Type Int: +, -, *, /, and mod.

1
2
3
4
9/1
- : int = 9
65 mod 60
- : int = 5

Type float: (must always contain a dot .)

1
2
3
4
3.
- : float = 3.
3
- : int = 3

Multiplication in float: *.

1
2
3.14 *. 2.
- : float = 6.28

OCaml will not auto convert between int and float.

To convert: int_of_float and float_of_int.

Type bool: true and false

Type char: write in single quote: 'c'

Convert bewteen int and char: char_of_int and int_of_char

Type string: write in double quote: "string"

concatenation operator: ^:

1
2
"abc" ^ "def"
- : string = "abcdef"

Convert int, float and bool to string:

1
2
3
4
string_of_int 42
- : string = "42"
String.make 1 'z'
- : string = "z"

Convert from a string:

1
2
3
int_of_string "123"
- : int = 123
int_of_string "not an int" --> error!

There is no char_of_string, but can use index operator:

1
2
"abc".[1]
- : char = 'b'

Operators = and <> examine structural equality whereas == and != examine physical equality.

3.2 If Expressions

Syntax: if e1 then e2 else e3

1
2
if 3 + 5 > 2 then "yay" else "boo"
- : string = "yay"

Expression: like “yay” and “boo” should have the same type.

If can be nested:

1
2
3
4
if e1 then e2
else if e3 then e4
...
else en

The final else is mandatory.

Dynamic semantics:

​ If e1 evaluates to true, and if e2 evaluates to a value v, then if e1 then e2 else e3 evaluates to v.

​ If e1 evaluates to false, and if e3 evaluates to a value v, then if e1 then e2 else e3 evaluates to v.

Static semantics:

​ If e1 has type bool and e2 has type t and e3 has type t then if e1 then e2 else e3 has type t.

3.3 Let Expressions

Syntax: let x = e1 in e2

x is an identifier, it must start with lower case, e1 is called the binding expression, e2 is called the body expression.

1
2
let x = 42 in x + 1
- : int = 43

Here we bind a value to the name x,then using that binding inside another expression, x+1.

Dynamic semantics:

To evaluate let x = e1 in e2:

  • Evaluate e1 to a value v1.
  • Substitute v1 for x in e2, yielding a new expression e2'.
  • Evaluate e2' to a value v2.
  • The result of evaluating the let expression is v2.

Example:

1
2
3
4
5
6
7
8
    let x = 1 + 4 in x * 3
--> (evaluate e1 to a value v1)
let x = 5 in x * 3
--> (substitute v1 for x in e2, yielding e2')
5 * 3
--> (evaluate e2' to v2)
15
(result of evaluation is v2)

Static semantics:

​ If e1 : t1 and if under the assumption that x : t1 it holds that e2 : t2, then (let x = e1 in e2) : t2.

1
let x : t = e1 in e2

3.4 Scope

The scope of a variable is where the name is meaningful.

1
2
3
4
5
let x = 42 in
(* y is not meaningful here *)
x + (let y = "3110" in
(* y is meaningful onyl meaningful inner the expression*)
int_of_string y)

3.5 Type Annotations

Syntax: (e : t)

parentheses are required.

A type annotation:

1
2
3
4
5
6
7
8
9
10
(5 : int)
- : int = 5

(5 : float) --> error--> Correct: (5. : float)
File "[27]", line 1, characters 1-2:
1 | (5 : float)
^
Error: This expression has type int but an expression was expected of type
float
Hint: Did you mean `5.'?

4. Functions

4.1 Function Definition

Syntax:

1
let rec f x1 x2 ... xn = e

Need rec keyword to make the function be recursive

Example 1:

1
2
3
4
5
(*Assuem n>0*)
let rec fact n =
if n = 0 then 1
else n * fact(n-1)
val fact : int -> int = <fun>

Example 2:

1
2
3
4
(** [pow x y] is [x] to the power of [y].
Requires: [y >= 0]. *)
let rec pow x y = if y = 0 then 1 else x * pow x (y - 1)
val pow : int -> int -> int = <fun>

If we wanna write down the type:

1
let rec pow (x : int) (y : int) : int = ...

Mutually recursive functions can be defined with the and keyword:

1
2
let rec f x1 ... xn = e1
and g y1 ... yn = e2

Example 3:

1
2
3
4
5
6
7
8
9
(** [even n] is whether [n] is even.
Requires: [n >= 0]. *)
let rec even n =
n = 0 || odd (n - 1)

(** [odd n] is whether [n] is odd.
Requires: [n >= 0]. *)
and odd n =
n <> 0 && even (n - 1);;

Syntax for Function Types:

1
2
3
t -> u
t1 -> t2 -> u
t1 -> ... -> tn -> u

~Take input of type t and return output of type u

~Take first input of type t1 and second input of type t2 and return output of type u

4.2 Anonymous Functions

Syntax:

1
fun x1 ... xn -> e

fun is a keyword

Example:

1
2
3
4
5
6
(*Ex1, take one param*)
(fun x -> x + 1) 30;;
- : int = 31
(*Ex2, take two param*)
(fun x y -> (x +. y) /. 2.) 32.1 43.43;;
- : float = 37.765

left-hand side is the function to be applied

right-hand side is the argument

4.3 Function Application

Syntax:

1
e0 e1 e2 ... en

No parentheses needed

Evaluation of e0 e1 e2 ... en

  1. Evaluate subexpression:

    E0 –> v0, … , en –> vn

    v0 must be a function:

    fun x1 ... xn --> e

  2. Substitute vi for xi in e yielding new expression e’.

    Evaluate it: e’ –> v

Example 1:

1
2
3
(fun x -> x + 1) (2+3)
(fun x -> x + 1) 5
5 + 1 --> 6

Left-hand side is Anonymous function already, no need to evaluate

(2 + 3) can be evaluated to 5, the apply to the function fun

Example 2:

1
2
3
(fun x y -> x - y) (3 * 1)(3 - 1)
(fun x y -> x - y) 3 2
3 - 2 --> 1

4.4 Polymorphic Functions

The identity function is the function that simply returns its input:

1
2
3
4
5
6
7
8
9
let id x = x
val id : 'a -> 'a = <fun>
id 5;;
- : int = 5
id "string"
- : string = "string"

let id = fun x -> x
val id : 'a -> 'a = <fun>

The 'a is a type variable: it stands for an unknown type.

Just like a regular variable stands for an unknown value.

Type variables always begin with a single quote.

Commonly used type variables include 'a, 'b, and 'c, which typically pronounce in Greek: alpha, beta, and gamma.