Introduction to OCaml programming language

Krzysztof Leśniak

@Serpent7776

fp-wroc meetup

26.05.2020

I'm not an expert,
I'm just a dude

- Scott Schurr, CppCon 2015

OCaml

OCaml is a general purpose programming language with an emphasis on expressiveness and safety
source

Some features

  • Static typing + type inference
  • Automatic memory management
  • REPL
  • Efficient native code compiler
  • Safety
  • Imperative features
  • Object oriented capabilities
  • Exceptions

Type inference


# let n = 1;;
val n : int = 1
						

# let f = 1.1;;
val f : float = 1.1
						

# let s = "hello";;
val s : string = "hello"
						

# fun x -> x + 2;;
- : int -> int = <fun>
						

# fun x y -> x + y;;
- : int -> int -> int = <fun>
						

Functions


# let add = fun x y -> x + y;;
val add : int -> int -> int = <fun>
						

# let add x y = x + y;;
val add : int -> int -> int = <fun>
						

# add 3 5;;
- : int = 8
						

# add (add 1 2) (add 3 4);;
- : int = 10
						

Currying


# let add x y = x + y;;
val add : int -> int -> int = <fun>
						

# let add x = fun y -> x + y;;
val add : int -> int -> int = <fun>
						

# let add2 = add 2;;
val add2 : int -> int = <fun>
						

# add2 5;;
- : int = 7
						

Recursive functions


let rec factorial n =
        if n > 0 then
                n * factorial (n - 1)
        else
                1
						

let rec is_even x =
        if x = 0 then true else is_odd (x - 1)
and is_odd x =
        if x = 0 then false else is_even (x - 1)
							
source

Custom operators


let (++) x y =
        2 * (x + y)
in
2 ++ 3
						
10

let cond_expr = (ws varname) >>= fun name ->
        (ws eqeq) *> (ws literal) >>| fun v ->
        Eq (name, v)
						

Pattern matching


let rec fact n =
        match n with
        | 0 -> 1
        | 1 -> 1
        | k -> k * fact (k - 1)
						

let rec fact = function
        | 0 -> 1
        | 1 -> 1
        | k -> k * fact (k - 1)
						

let rec sum = function
        | [] -> 0
        | hd :: tl -> hd + sum tl
						

Type system


# 1 + 2 + 3;;
- : int = 6
						

# 1.0 + 2.0;;
						
1.0 + 2.0;;
^^^
Error: This expression has type float
but an expression was expected of type int
						

# (+);;
- : int -> int -> int = <fun>
						

# (+.);;
- : float -> float -> float = <fun>
						

# 1.2 +. 1.3;;
- : float = 2.5
						

Type system


# 1 + 1.0;;
						
1 + 1.0;;
    ^^^
Error: This expression has type float
but an expression was expected of type int
						

# float_of_int;;
- : int -> float = <fun>
						

# (float_of_int 1) +. 1.0;;
- : float = 2.
						

String formatting


# let x = 1;;
val x : int = 1
						

# "value of x is " ^ (string_of_int x);;
- : string = "value of x is 1"
						

# Printf.sprintf "value of x is %d" x;;
- : string = "value of x is 1"
						

# Printf.sprintf "%d, %.1f, %s\n" 12 1.5 "hello";;
- : string = "12, 1.5, hello\n"
						

# Printf.sprintf "%d" 1.5;;
						
Printf.sprintf "%d" 1.5;;
                    ^^^
Error: This expression has type float
but an expression was expected of type int
						

Formatted Output


# let name = "Chris" in
        Printf.printf "Hello, %s\n" name;;
						
Hello, Chris
						

# Printf.printf "Hello, %s\n" 42;;
						
Printf.printf "Hello, %s\n" 42;;
                            ^^
Error: This expression has type int
but an expression was expected of type string
						

Formatted Input


# Scanf.scanf "%s" (fun s ->
        Printf.printf "hello, %s\n" s
);;
						

# Scanf.scanf "%s %s" (fun s1 s2 ->
        Printf.printf "hello %s and %s\n" s1 s2
);;
						

Imperative features


let factorial n =
        let result = ref 1 in
        for i = 2 to n do
                result := !result * i
        done;
        !result
in
Printf.printf "%d\n" (factorial 6)
						
720

Variants


# [1; 2; 3];;
- : int list = [1; 2; 3]
						

# [1; 2; "foo"];;
						
[1; 2; "foo"];;
       ^^^^^
Error: This expression has type string
but an expression was expected of type int
						

type variant =
        | Int of int
        | String of string
						

let ls = [Int 1; Int 2; String "foo"]
						

Recursive variants


type binary_tree =
    | Leaf of int
    | Tree of binary_tree * binary_tree
						

# Tree ((Leaf 1), (Leaf 2));;
- : binary_tree = Tree (Leaf 1, Leaf 2)
						

Parametrized variants


type 'a binary_tree =
    | Leaf of 'a
    | Tree of 'a binary_tree * 'a binary_tree
						

# Tree ((Leaf 1), (Leaf 2));;
- : int binary_tree = Tree (Leaf 1, Leaf 2)
						

# Tree ((Leaf "foo"), (Leaf "bar"));;
- : string binary_tree = Tree (Leaf "foo", Leaf "bar")
						

Example - factorial


let rec fact = function
        | 0 -> 1
        | 1 -> 1
        | n -> n * fact (n - 1)
in
Scanf.scanf "%d" (fun n ->
        Printf.printf "%d\n" (fact n)
)
						

let fact n =
        let rec proc acc = function
                | 0|1 -> acc
                | k -> proc (k * acc) (k - 1)
        in proc 1 n
in
Scanf.scanf "%d" (fun n ->
        Printf.printf "%d\n" (fact n)
)
						

let fact n =
        if n < 0 then
                raise (Invalid_argument
                        "negative number given")
        else
                let rec proc acc = function
                        | 0|1 -> acc
                        | k -> proc (k * acc) (k - 1)
                in proc 1 n
in
Scanf.scanf "%d" (fun n ->
        Printf.printf "%d\n" (fact n)
)
						

Example - fizzbuzz


let fizzbuzz i = match (i mod 3, i mod 5) with
        | (0,0) -> "fizzbuzz"
        | (_,0) -> "buzz"
        | (0,_) -> "fizz"
        | (_,_) -> string_of_int i
in
let print_fizzbuzz i =
        print_endline (fizzbuzz i)
in
Scanf.scanf "%i" print_fizzbuzz
						
source

Tools

opam
package management and switch management
dune
popular build system for ocaml
js_of_ocaml, bucklescript
ocaml to javascript transpiler
merlin
IDE features for Vim, Emacs and other
utop
awesome interactive mode for ocaml

Real world usages

  • ocaml standard library
  • haxe programming language compiler
  • coq formal proof management system
  • MirageOS library operating system for building unikernels
  • fftw library for computing the discrete Fourier transform
  • flow type checker for javascript
  • pyre type checker for python
  • Jane Street Capital high-frequency trading company

Web

A language that doesn't affect the way you think about programming is not worth knowing.

Alan J. Perlis, Epigrams on Programming, 1982

Thank you

@Serpent7776
https://serpent7776.itch.io/
https://dev.to/serpent7776