Willem Hoek

OCaml notes

Mar 07, 2019

Install OCaml

Install on Linux

sudo apt-get update -y && apt-get upgrade -y
sudo apt-get install m4 patch ocaml -y

Install OPAM as per notes https://opam.ocaml.org/doc/Install.html

sudo apt-get install opam

else

wget https://raw.github.com/ocaml/opam/master/shell/opam_installer.sh -O - | sh -s /usr/local/bin

Install rest via opam

opam init
opam update
opam upgrade
opam switch
opam switch list-available
opam switch list-available base
opam switch create 4.12.0+mingw64c 

# you could have multiple switches of same version
opam switch create myname  4.12.0+mingw64c 


This will take a few minutes.

For installed version of OCaml - get required tools/libraries via opam, e.g.

opam install utop tuareg merlin user-setup dune
opam user-setup install

For OCaml on Windows (cygwin):

opam install depext depext-cygwinports

Better to use following to install packages – as it take care of dependencies. E.g. to install sqlite3 package

opam depext -i sqlite3

Skeleton project

https://stackoverflow.com/questions/67398198/

You can use dune to create a skeleton project

dune init proj demo

This will create a demo folder that will have the OCaml project skeleton ready to use.

cd demo

The main.ml is in the bin folder. To build and execute the project.

dune build
dune exec demo

To execute demo.ml that is in the test folder

dune test

To open project in utop

dune utop

Reference documents

OCaml website - https://ocaml.org/docs

Cheat sheets - https://v2.ocaml.org/docs/cheat_sheets.html

The OCaml Manual - https://caml.inria.fr/pub/docs/manual-ocaml/

Core Library - https://caml.inria.fr/pub/docs/manual-ocaml/libref/index.html

Pattern match

https://ocaml.org/learn/tutorials/data_types_and_matching.html#Pattern-matching-on-datatypes

(*    pair : int * int -> int -> int = <fun>    *)

let pair k p =
  match k, p with
  | (1, _), _ -> 1
  | _, 2 -> 222
  | _, _ -> 0

The next are are the same.

(*    first : int list -> string = <fun>    *)

let first l =
  match l with
  | a :: b :: _ when a = b -> "double"
  | 1 :: _ -> "one"
  | _ -> "other"

let first = function
  | a :: b :: _ when a = b -> "double"
  | 1 :: _ -> "one"
  | _ -> "other"

Lists

https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html

let a = List.init 5 (fun x -> x * 2);;
(* int list = [0; 2; 4; 6; 8]   *)

List.map (fun x -> x * 2) a;;
(* int list = [0; 4; 8; 12; 16]  *)

List.iter (fun x -> print_int x) a;;
(* 02468 *)

List.iteri (fun i x -> print_int (x + i)) a;;
(* 036912   *)

Avoid using for loop when List.iter can be used.

let my_list = [1;2;3;4]

let () = 
  for n = 0 to (List.length my_list - 1) do
    print_int (List.nth my_list n)
  done
(* 1234 *)

let () = List.iter print_int my_list
(* 1234 *)

Arrays

https://caml.inria.fr/pub/docs/manual-ocaml/libref/Array.html

Array.make 5 1;;
(* int array = [|1; 1; 1; 1; 1|]    *)

Array.init 5 (fun x -> x + 1);;
(* int array = [|1; 2; 3; 4; 5|]     *)

let a = Array.make_matrix 2 3 1;;     (* where x=2  y=3 *)
(* val a : int array array = [|[|1; 1; 1|]; [|1; 1; 1|]|]   *)

a.(0).(0) <- 100;;
a;;
(* int array array = [|[|100; 1; 1|]; [|1; 1; 1|]|]   *)
let create_grid n = Array.init n (fun y ->
                        Array.init n (fun x ->
                            y * n + x
                          )
                      )

let print_grid g =
  let n = Array.length g in
  for y = n-1 downto 0  do
    for x = 0 to n-1 do
      Printf.printf "%3i%!" g.(x).(y)
    done;
    Printf.printf "\n%!"
  done

let a = create_grid 3
(* val a : int array array = [|[|0; 1; 2|]; [|3; 4; 5|]; [|6; 7; 8|]|] *)

let () = print_grid a
(*
  2  5  8
  1  4  7
  0  3  6
 *)

Named and Default arguments

(* ~foo -- named argument *)

let div ~top y  = top  / y;;

(* or *)
let div ~top:x y  = x / y;;

div 8 2;;
(* 4 *)

div 2 ~top:8;;
(* 4 *)

(* ?bar -- Named argument with a default. Cannot be used with last argument. *)
let f1  ?a:(aa=4) ~b c = aa + b  + c;;
(* val f1 : ?a:int -> b:int -> int -> int  *)

let f2  ?(a=4) ~b c = a + b  + c;;
(* val f2 : ?a:int -> b:int -> int -> int  *)

f1 1 2;;
(* 7 *)

f1 1 2 3;;
(* Error: This argument cannot be applied without label *)

f1 ~a:3 ~b:1 2;;
(* 6 *)

From https://github.com/lcoviedo/mirage-static-monitor/blob/master/dispatch.ml

let red fmt    = Printf.sprintf ("\027[31m"^^fmt^^"\027[m")
let green fmt  = Printf.sprintf ("\027[32m"^^fmt^^"\027[m")
let yellow fmt = Printf.sprintf ("\027[33m"^^fmt^^"\027[m")
let blue fmt   = Printf.sprintf ("\027[36m"^^fmt^^"\027[m")

let () = Printf.printf "%s\n" (red "this is red") 
let () = Printf.printf "%s\n" (green "this is green")
let () = Printf.printf "%s\n" (yellow "this is yellow")
let () = Printf.printf "%s\n" (blue "this is blue")

Related Posts

Solving the Jane Street puzzle of December 2022

Why I created Scrumdog - a program to download Jira Issues to a local database

Jane Street puzzle Feb 2021 SOLVED! OCaml to the rescue

Solving the Jane Street puzzle of Dec 2020 - Backtracking with OCaml

Automate your Jira reporting with Python and Excel

Solving the Jane Street Puzzle of June 2020; Circle Time