DarkMatter in Cyberspace
  • Home
  • Categories
  • Tags
  • Archives

Ocaml Notes


Ocaml is the only language with the following feature:

  • Static type

  • Compile to native binary code

  • Powerful REPL

  • Strong FP support

Haskell is another one with these features, but it goes too far.

Nim is also a good candidate, however, without REPL.

Install

Install Ocaml, package manager Opam, and REPL utop with asdf:

asdf plugin-add ocaml
asdf list-all ocaml
asdf install ocaml 4.10.0  # takes a few minutes
asdf global ocaml 4.10.0

asdf plugin-add opam
asdf list-all opam
asdf install opam 2.0.6
asdf global opam 2.0.6
http_proxy=http://localhost:1080 https_proxy=http://localhost:1080 opam init
opam install utop    # takes a few minutes
utop    # utop is the ipython for python

Ref: Step-by-Step Guide to Manage OCaml Installations With asdf

Vim Integration

opam install merlin
opam user-setup install

Frequently Used Operations

Print function signiture

Input function name in utop, for example:

utop # List.filter;;
- : 'a list -> f:('a -> bool) -> 'a list = <fun>

Here utop # is the prompt instead of codes written by user, the same below.

Read Files

Install Core with opam install core and add the following lines into ~/.ocamlinit:

#use "topfind";;
#thread
#require "core.top"
#require "core.syntax"

Read file contents with:

let res = Core.In_channel.read_all "filename.txt";;

String match

For example, test if str keyword in filelist:

utop # #require "core";;
utop # #require "str";;
utop # let filter_files (filelist: string list) (keyword: string): string list =
  let str_in_file kw filename =
    let lines = Core.In_channel.read_lines filename in
    let kw_reg = Str.regexp (".*" ^ kw ^ ".*") in
    let matched = List.filter lines (fun line -> Str.string_match kw_reg line 0) in
    match List.length matched with
      0 -> false
    | _ -> true
  in
  List.filter filelist (fun afile -> str_in_file keyword afile);;

utop # let files = ["/home/leo/apps/dsnote/notes.sh"; "/home/leo/apps/dsnote/README.md"];;
utop # let res = filter_files files "power";;
val res : string list = ["/home/leo/apps/dsnote/README.md"]

Using 3rd Party Libraries

In REPL

To use a 3rd party library in REPL, for example "Core" here, you should #require it:

#require "core.top"
#require "core.syntax"

let res = Core.In_channel.read_all "filename.txt";;

#require is a command of toplevel, instead of a Ocaml function, so it can't be used in source file.

Do NOT use open, it will mess up the namespace. For example, List.filter and Core.List.filter has different signatures. If you open Core in REPL while not in script file, List.filter ... will fail when compiled by ocamlopt but pass in REPL.

Compile sources

Prefix the compilation command with ocamlfind, and add -package <pkg_name> into the compilatin command:

cat << EOF > read_file.ml
let () = 
  let res = Core.In_channel.read_all Sys.argv.(1) in
  print_endline res
EOF

ocamlbuild -pkgs core read_file.native
./read_file.native ~/.asdf/LICENSE

ocamlfind ocamlopt -o readfile -linkpkg -thread -package core read_file.ml
./readfile ~/.asdf/LICENSE

ocamlbuild is prefered to ocamlfind for cleaner syntax.

ocamlfind can only find packages listed in ocamlfind list. Get the location of the package with ocamlfind query <pkg-name>, for example ocamlfind query core.

Ref:

Compiling OCaml projects



Published

Mar 31, 2020

Last Updated

Apr 13, 2020

Category

Tech

Tags

  • ocaml 1

Contact

  • Powered by Pelican. Theme: Elegant by Talha Mansoor