How do I setup ocamlinit so that ppx works? - ocaml

This is my ocamlinit:
(* Added by OPAM. *)
let () =
try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
with Not_found -> ()
;;
(* ## added by OPAM user-setup for ocamltop / base ## 3ec62baf6f9c219ae06d9814069da862 ## you can edit, but keep this line *)
#use "topfind";;
(* ## end of OPAM user-setup addition for ocamltop / base ## keep this line *)
#thread;;
(* #ppx "ppx-jane -as-ppx";; *)
#require "ppx_jane";;
#require "core.top";;
#require "async";;
#require "core_extended";;
open Core.Std;;
With this exactly, I get this in utop
utop # type test = char list [##deriving show];;
Error: Cannot locate deriver show
If I use the line beginning with #ppx instead of #require "ppx_jane", I get this error
utop # type test = char list [##deriving show];;
Error: ppx_type_conv: 'show' is not a supported type type-conv generator
How should I set up ocamlinit to use [##deriving show]?

I managed to have it working using #require "ppx_deriving.show";; (with or without #require "ppx_jane";;).

In addition to Pierre's suggestion, I found that I needed the line with ppx_jane.
Also, I used #require "ppx_deriving.std" instead of just ppx_deriving.show to get ord and the rest of the stuff too.
Here's my full ocamlinit
(* Added by OPAM. *)
let () =
try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
with Not_found -> ()
;;
(* ## added by OPAM user-setup for ocamltop / base ## 3ec62baf6f9c219ae06d9814069da862 ## you can edit, but keep this line *)
#use "topfind";;
(* ## end of OPAM user-setup addition for ocamltop / base ## keep this line *)
#thread;;
#require "ppx_jane";;
#require "core.top";;
#require "async";;
#require "core_extended";;
#require "ppx_deriving.std";;
open Core.Std;;

Related

OCaml refer to module in ml file inside mli

Here I have a file set.ml with a module called IntSet. How do I refer to the module IntSet inside the corresponding interface file set.mli?
module IntSet = struct
type t = int list;;
let empty = [];;
let rec is_member key = function
| [] -> false
| (x::xs) -> (
if x = key then true
else is_member key xs
);;
end;;
let join xs ys = xs # ys;;
Here is set.mli
val join : IntSet.t -> IntSet.t -> IntSet.t
If I try to compile it, I get an error claiming that the module IntSet is unbound.
% corebuild set.native
+ ocamlfind ocamlc -c -w A-4-33-40-41-42-43-34-44 -strict-sequence -g -bin-annot -short-paths -thread -package core -ppx 'ppx-jane -as-ppx' -o set.cmi set.mli
File "set.mli", line 1, characters 11-19:
Error: Unbound module IntSet
Command exited with code 2.
Hint: Recursive traversal of subdirectories was not enabled for this build,
as the working directory does not look like an ocamlbuild project (no
'_tags' or 'myocamlbuild.ml' file). If you have modules in subdirectories,
you should add the option "-r" or create an empty '_tags' file.
To enable recursive traversal for some subdirectories only, you can use the
following '_tags' file:
true: -traverse
<dir1> or <dir2>: traverse
Compilation unsuccessful after building 3 targets (1 cached) in 00:00:00.
How do I expose a module defined in set.ml so I can use it in definitions?
I changed set.mli to this, and the compiler seems happy:
module IntSet : sig type t end
val join : IntSet.t -> IntSet.t -> IntSet.t
There is probably more work to make things usable. There's no way to make a value of type IntSet.t, for example.

ocaml bitstring within a script

In ocaml toplevel, I can use "bitstring" package by typing the following commands:
#use "topfind";;
#camlp4o;;
#require "bitstring.syntax";;
let data = 0l;;
let bits = BITSTRING { data : 32 };;
However, if I create an OCaml script, e.g., foo.ml :
#!/usr/bin/env ocaml
#use "topfind";;
#camlp4o;;
#require "bitstring.syntax";;
let data = 0l;;
let bits = BITSTRING { data : 32 };;
And, if I run the OCaml script, I got a syntax error:
$ ./foo.ml
File "./foo.ml", line 8, characters 28-29: Error: Syntax error
What am I missing here? Why does the same code work with an interactive shell, but not with a script file?
I believe that's because script file is first parsed, and then the directives are executed, hence it cannot handle unknown (yet) syntax.
The easiest solution is to use ocamlscript :
#! /usr/bin/env ocamlscript
Ocaml.packs := [ "bitstring"; "bitstring.syntax" ]
--
let data = 0l;;
let bits = BITSTRING { data : 32 };;

Use OUnit module in OCaml - Unbound module OUnit error

I'm trying to use OUnit with OCaml.
The unit code source (unit.ml) is as follows:
open OUnit
let empty_list = []
let list_a = [1;2;3]
let test_list_length _ =
assert_equal 1 (List.length empty_list);
assert_equal 3 (List.length list_a)
(* etc, etc *)
let test_list_append _ =
let list_b = List.append empty_list [1;2;3] in
assert_equal list_b list_a
let suite = "OUnit Example" >::: ["test_list_length" >:: test_list_length;
"test_list_append" >:: test_list_append]
let _ =
run_test_tt_main suite
With ocamlc unit.ml, I got an error message Error: Unbound module OUnit. Why is this? How can I use the OUnit in OCaml. I installed OUnit with opam.
You should use for example:
ocamlfind ocamlc -package oUnit -linkpkg -o unit unit.ml
ocamlfind is an utility that encapsulates lookup of installed libraries. You can also avoid composing compiler-invocation yourself and use a build tool.

OCaml int to binary string conversion

What's the easiest way to convert an Int32.t to binary? For example:
-1 -> "\255\255\255\255" ?
Edit:
To use extlib, install it with yum and in the toplevel:
#use "topfind";;
#require "extlib";;
I would suggest using Bitstring for this kind of thing. You can find it here.
For example, in the toplevel:
# #use "topfind";;
# #camlp4o;;
# #require "unix";;
# #require "bitstring.syntax" ;;
# let data = Int32.of_int (-1);;
# let bits = BITSTRING { data: 32 } ;;
then you can perform various conversions on the bitstring including writing it to a binary file or to stdout or to a string:
# Bitstring.string_of_bitstring bits ;;
- : string = "\255\255\255\255"
Use extlib:
# let io = IO.output_string ();;
val io : string IO.output = <abstr>
# IO.write_i32 io (-1);;
- : unit = ()
# IO.close_out io;;
- : string = "\255\255\255\255"

Error: Unbound module ... in Ocaml

I have just installed a library called Apron, the installation seems to be done:
#ubuntu$ find -name "*apron*"
./lib/libapron_debug.so
./lib/libapron.a
./lib/libapron.so
./lib/libapron_debug.a
./local/lib/ocaml/3.11.2/stublibs/dllapron_caml.so.owner
./local/lib/ocaml/3.11.2/stublibs/dllapron_caml.so
./local/lib/ocaml/3.11.2/apron
./local/lib/ocaml/3.11.2/apron/libapron_caml_debug.a
./local/lib/ocaml/3.11.2/apron/apron.cmxa
./local/lib/ocaml/3.11.2/apron/libapron_caml.a
./local/lib/ocaml/3.11.2/apron/apron.cmi
./local/lib/ocaml/3.11.2/apron/apron.cmx
./local/lib/ocaml/3.11.2/apron/apron.a
./local/lib/ocaml/3.11.2/apron/apron.cma
And I tried a first example:
(* with default setting:
apronppltop -I $MLGMPIDL_INSTALL/lib -I $APRON_INSTALL/lib
#load "gmp.cma";;
#load "apron.cma";;
#load "box.cma";;
#load "oct.cma";;
#load "polka.cma";;
#load "ppl.cma";;
#load "polkaGrid.cma";;
#install_printer Apron.Linexpr1.print;;
#install_printer Apron.Texpr1.print;;
#install_printer Apron.Lincons1.print;;
#install_printer Apron.Generator1.print;;
#install_printer Apron.Abstract1.print;;
let environment_print fmt x = Apron.Environment.print fmt x;;
let lincons1_array_print fmt x = Apron.Lincons1.array_print fmt x;;
let generator1_array_print fmt x = Apron.Generator1.array_print fmt x;;
#install_printer Apron.Var.print;;
#install_printer environment_print;;
#install_printer lincons1_array_print;;
#install_printer generator1_array_print;; *)
open Apron;;
...
However ocaml -c file.ml gives me Error: Unbound module Apron which happens on open Apron;;
Does anyone know why I could not load the Apron module? Thank you very much!
I should indicate the path of the Apron library with '-I' options. As it is installed in the standard library of OCaml, you only need to compile with:
ocamlc -I +apron -c file.ml