Project setup

# setup opam
opam init
# install OCaml
opam switch create 4.10.0
# update environment
eval $(opam env)
# install packages
opam install dune utop merlin ocp-indent ocamlformat

If you just need to meddle with a single file, create a dune file along with it and you’re good to go:

(executable
  (name      main)
  (libraries base other_lib))

main is nothing but the name correspond to the file main.ml, or whatever you file name is. When you run dune build main.exe it’ll generate an executable inside ./_build/default/main.exe which you can run with. Or you can use dune exec ./main.exe which combines building and running an executable into a single operation. Use opam to install whatever libraries you need and add them to libraries stanza.

Now to work with multiple files, read the dune document first. This is an example:

.:
bin  dune-project  my-proj.opam  src

./bin:
dune  main.ml

./src:
ast.ml  dune  lexer.mll  other.ml  parser.mly
; file: dune-project
(lang dune 2.6)
(name my-proj)
; you can ignore this.
(using menhir 2.1)
; file: ./bin/dune
(executable
 (name main)
 (libraries lib))
; file: ./src/dune
(library
 (name lib))
; you can ignor this.
(ocamllex lexer)
(menhir (modules parser))

Note that if you want to run dune utop and automatically load modules, it has to be a library. So I setup main.ml as an entry point and keep my source files is src, aka a library.


Emacs setup

You can check out my setup.


OCaml

OCaml doesn’t have a function composition operator like the Haskell .. Here is a discussion, TLDR: OCaml doesn’t favor point-free style.

OCaml doesn’t have ad hoc polymorphism, it’s the reason you have print_string and print_int instead of a single print. You may know this as overloading in other languages. Modular implicits is OCaml’s way to support it, but it seems not under active development. Here is a discussion, TLDR: Multicore is more important.

Haskell’s functor and OCaml’s functor are not the same thing, although they both got the name from Category Theory. OCaml’s functor works on module. In short it’s a parametrized module which is a module that takes another module(s) as argument(s) and outputs a module.

You may already know that modules took an important role in OCaml. They’re not like other languages where they exists just to separate namespaces or import namespaces. OCaml’s module system provides abstraction and composition. It also makes compilation very fast because it ensure that each module can be typechecked and compiled incrementally.

Java’s Generic and Interfaces provides something similar to OCaml module system, here is an example of OCaml generic Set.

module type OrderedType = sig
  type t
  val compare : t -> t -> int
end

module IntType = struct
  type t = int
  let compare x y = x - y
end

module IntSet = Set.Make(IntType)

(* And since OCaml's Int module already have these, you can just use it *)
module IntSet' = Set.Make(Int)

However Java doesn’t support higher kinded polymorphism, simply put, you can only abstract over type(Set) but not type constructor(T). For example, you want to abstract over the notion of a tree which is something with nodes and leafs and you don't care what the nodes actually are, here is how you do it:

module Tree (F : sig type 'a t end) = struct
  type 'a t = Leaf of 'a | Node of ('a t) F.t
end

(* And here we can create Rose Tree or Binary Tree *)
module RoseTree = Tree (struct type 'a t = 'a list end)
module BinTree = Tree (struct type 'a t = 'a * 'a end)

And if you want to get your hands dirty with front end, there is ReasonML.

That’s about it, here are some helpful resources: