(js_of_ocaml) how to solve "Error: Unbound module Js"? - ocaml

I want to re-compile a set of files to generate a .js file in my Mac. It used to work (long time ago), I don't know why it does not work anymore.
It returned:
$ make analyzejs
ocamlfind ocamlc -g unix.cma -package js_of_ocaml.ppx -I /Users/chengtie/lib -I hack -I functor -I params -I concrete -I pd -I ai -I domains -I frontend -I frontend/gen -I syntax -I lib -I main -I rules -I area -I values -I vars -I zones -I microsoft -I experiment -I expression -I abstract -I operator -I ev -I js -I /Users/chengtie/.opam/4.02.3/lib/xmlm -annot -c lib/array2_js.ml
File "lib/array2_js.ml", line 17, characters 50-54:
Error: Unbound module Js
my lib/array2_js.ml:
open Array2
module Array2_js:
sig
val of_js: (('a Js.js_array Js.t) Js.js_array Js.t) -> ('a -> string) ->
string array array
val of_js_shift :int -> int -> 'b ->
(('a Js.js_array Js.t) Js.js_array Js.t) -> ('a -> 'b) -> 'b array array
val of_js_f2_shift: int -> int -> 'b ->
(('a Js.js_array Js.t) Js.js_array Js.t) ->
(('a Js.js_array Js.t) Js.js_array Js.t) ->
('a -> 'a -> 'b) -> 'b array array
end
=
struct
(* {can better}: don't know why f:'a -> 'b is not permitted; *)
let of_js (s: ('a Js.js_array Js.t) Js.js_array Js.t) (f: 'a -> string) :
string array array =
let s = Js.to_array s in
let num_rows = Array.length s in
let num_columns = Array.length (Js.to_array s.(0)) in
(* pffo "num_rows_1: %d, num_columns_1: %d\n" num_rows num_columns; *)
let t = Array2.make num_rows num_columns "" in
$ js_of_ocaml --version returned 3.5.2.
Could anyone help?

open Js_of_ocaml at the top of array2_js.ml
update the command line with -package js_of_ocaml-ppx (instead of -package js_of_ocaml.ppx

Related

difference between dune utop and utop

If I load the following code in utop, after #require "mparser", it is accepted in the top level and give the signature below
open MParser
let infix p op = Infix (p |>> (fun _ a b -> (`Binop (op, a, b))), Assoc_left)
let operators =
[
[
infix (char '*') `Mul;
infix (char '/') `Div;
];
[
infix (char '+') `Add;
infix (char '-') `Sub;
];
]
let decimal = many1_chars digit |>> int_of_string
let term = (decimal |>> fun i -> `Int i)
let expr s = expression operators term s
let rec calc = function
| `Int i -> i
| `Binop (op, a, b) ->
match op with
| `Add -> calc a + calc b
| `Sub -> calc a - calc b
| `Mul -> calc a * calc b
| `Div -> calc a / calc b
accepted by utop as
val infix :
('a, 'b) MParser.t ->
'c -> ([> `Binop of 'c * 'd * 'd ] as 'd, 'b) MParser.operator = <fun>
val operators :
(_[> `Binop of _[> `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ]
as 'a, unit)
MParser.operator list list =
[[Infix (<fun>, Assoc_left); Infix (<fun>, Assoc_left)];
[Infix (<fun>, Assoc_left); Infix (<fun>, Assoc_left)]]
val decimal : (int, unit) MParser.t = <fun>
val term : ([> `Int of int ], unit) MParser.t = <fun>
val expr :
unit MParser.state ->
(_[> `Binop of _[> `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ]
as 'a, unit)
MParser.reply = <fun>
val calc :
([< `Binop of [< `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ] as 'a) ->
int = <fun>
Now, if I try to load with dune utop a library containing this code as a file/module, I received the following error :
~$ dune utop lib
ocamlc lib/.lib.objs/lib__VariantExemple.{cmi,cmo,cmt} (exit 2)
(cd _build/default && /usr/local/bin/ocamlc.opt -w #a-4-29-40-41-42-44-45-48-58-59-60-40 -strict-sequence -strict-formats -short-paths -keep-locs -g -bin-annot -I lib/.lib.objs -I lib/.lib.objs/.private -I /Users/nrolland/.opam/system/lib/bytes -I /Users/nrolland/.opam/system/lib/mparser -I /Users/nrolland/.opam/system/lib/re -I /Users/nrolland/.opam/system/lib/re/perl -I /Users/nrolland/.opam/system/lib/seq -no-alias-deps -opaque -open Lib -o lib/.lib.objs/lib__VariantExemple.cmo -c -impl lib/variantExemple.ml)
File "lib/variantExemple.ml", line 5, characters 4-13:
Error: The type of this expression,
(_[> `Binop of _[> `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ]
as 'a, '_weak1)
operator list list, contains type variables that cannot be generalized
It looks like there are some type annotation missing.
I am not too familiar with polymorphic variant type and , is there an obvious solution out ?
I was hoping that sticking the signature part given by utop in an interface would work, but it does not seem to be valid in a .mli file
Edit : the simple solution is to add a closed type annotation.
let operators : ([ `Binop of [ `Add | `Div | `Mul | `Sub ] * 'a * 'a | `Int of int ] as 'a, unit) operator list list =
I am not sure if there is a reason for why an interactive session and a dune utop lib one-shot loading should behave differently
You have _ in front of your types, which suggest your type is weakly polymorphic, and the compiler refuse to let such things live in a compiled object.
you can get the same result with the mwe :
let store = ref None
The toplevel is ok with that as it can be resolved to a monomorphic type later if you evaluate something like store:= Some1, which "monomorphise" the type from _a option ref to int option ref

show_module tediousness in utop

I am using OCaml utop, with Core.Std module.
To see the help on a module, I have to follow the link of aliases like so:
utop # #show_module Array;;
module Array = Core_kernel.Std_kernel.Array
utop # #show_module Core_kernel.Std_kernel.Array;;
module Array = Core_kernel.Std_internal.Array
utop # #show_module Core_kernel.Std_internal.Array;;
module Array = Core_kernel.Core_array
And finally show_module on that will show the information. Is there a quicker way?
For completeness, the pull request mentioned by Daniel in the comments has been merged since, and now utop is smarter when it comes to #show_module.
utop # #show_module Array;;
module Array = Base__.Array
module Array = Base.Array
module Array :
sig
type 'a t = 'a array
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
val t_of_sexp : (Sexp.t -> 'a) -> Sexp.t -> 'a t
val sexp_of_t : ('a -> Sexp.t) -> 'a t -> Sexp.t
[...]
end

Use Async to make an GET request

Taken from the chapter 18 of the Real World OCaml book, I'm trying to break down the example given.
My scope, to just make the GET call and print something of the JSON we get back.
This is my code ( it's supposed to be a subset of the example given )
(* libraries *)
open Core.Std
open Async.Std
(* Generate a DuckDuckGo search URI from a query string *)
let query_uri query =
let base_uri = Uri.of_string "http://api.duckduckgo.com/?format=json" in
Uri.add_query_param base_uri ("q", [query])
(* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *)
let get_definition_from_json json_string =
match Yojson.Safe.from_string json_string with
| `Assoc kv_list ->
let find key =
begin match List.Assoc.find kv_list key with
| None | Some (`String "") -> None
| Some s -> Some (Yojson.Safe.to_string s)
end
in
begin match find "Abstract" with
| Some _ as x -> x
| None -> find "Definition"
end
| _ -> None
(* Execute the DuckDuckGo search *)
let get_definition word =
print_endline ("get_definition word:" ^ word);
Cohttp_async.Client.get (query_uri word)
>>= fun (_, body) ->
Pipe.to_list (Cohttp_async.Body.to_pipe body)
>>| fun strings ->
(word, get_definition_from_json (String.concat strings))
(* run *)
let () =
get_definition "OCaml"
>>= fun (word, def) ->
print_endline ("- word: " ^ word);
(
match def with
| None -> print_endline "[EMPTY]"
| Some str -> print_endline str
)
My issue is that I get this error when compiling:
ocaml setup.ml -build
Finished, 0 targets (0 cached) in 00:00:00.
+ /Users/antouank/.opam/system/bin/ocamlfind ocamlc -c -g -annot -bin-annot -thread -package yojson -package threads -package textwrap -package re2 -package core -package cohttp.async -I src -o src/main.cmo src/main.ml
File "src/main.ml", line 48, characters 18-41:
Error: This expression has type unit but an expression was expected of type
'a Async.Std.Deferred.t = 'a Async_kernel.Deferred0.t
Command exited with code 2.
Compilation unsuccessful after building 2 targets (0 cached) in 00:00:00.
E: Failure("Command ''/usr/local/bin/ocamlbuild' src/main.native -use-ocamlfind -tag debug' terminated with error code 10")
make: *** [build] Error 1
How can I get the string out of that Deferred, and what does that error mean exactly?
In the book, the example is run with a weird Command wrap, so I cannot see how to pull it out.
The problem in your definition of run is that the anonymous function
fun (word, def) ->
print_endline ("- word: " ^ word);
(
match def with
| None -> print_endline "[EMPTY]"
| Some str -> print_endline str
)
is not correctly typed to be used with a monadic operator >>=. It has type string * string -> unit while the >>= would here expect a function of type string * string -> unit Deferred.t.
If you look at the example of an echo server in the very same chapter, it will suggest the following approach:
let run () =
get_definition "OCaml"
>>= fun (word, def) ->
print_endline ("- word: " ^ word);
(
match def with
| None -> print_endline "[EMPTY]"
| Some str -> print_endline str
);
Deferred.return()
let () =
ignore(run ());
never_returns (Scheduler.go ())

Inspect operator |> in OCaml's toplevel?

I'd like to see the type of the operator |>, which is of course defined as let |> x f = f x;;.
With other operators, like +, I can simple hit (+);; and the toplevel will tell me it's - : int -> int -> int = <fun>.
But with |>, it says:
Error: Failure: "|> must be applied to two arguments"
My question is, how can I inspect operator |> in OCaml's toplevel.
Append:
OK. Now I know it has something to do with Core. If I define it directly it's OK. But in Core environment it just breaks.
This is my .ocamlinit:
(* Added by OPAM. *)
let () =
try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
with Not_found -> ()
;;
#use "topfind";;
#thread;;
#camlp4o;;
#require "core.top";;
#require "core.syntax";;
open Core.Std;;
It works for me. Here's a complete command line session:
$ ocaml
OCaml version 4.01.0
# let (|>) x f = f x;;
val ( |> ) : 'a -> ('a -> 'b) -> 'b = <fun>
# (|>);;
- : 'a -> ('a -> 'b) -> 'b = <fun>
#
Update
(Pascal Cuoq clearly has the right answer in the comments below. :-)

"Error: The function applied to this argument has type ..." when using named parameters

I'm currently working through "Real Word OCaml", and one of the basic examples with named / labeled parameters doesn't seem to work (using utop 4.01.0):
let languages = ["OCaml"; "Perl"; "C"];;
List.map ~f:String.length languages;;
Produces:
Error: The function applied to this argument has type 'a list -> 'b list
This argument cannot be applied with label ~f
Whereas:
List.map String.length languages;;
Produces the expected output [5; 4; 1].
caml.inria.fr mentions that:
In the core language, as in most languages, arguments are anonymous.
Does this mean that I have to include some kind of external library to make this code work ?
EDIT
Here's my ~/.ocamlinit file (as per the installation instructions for the book):
(* Added by OPAM. *)
let () =
try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
with Not_found -> ()
;;
#use "topfind"
#camlp4o
#thread
#require "core.top"
#require "core.syntax"
As mentioned in #rafix's comment, this can be fixed by putting
open Core.Std ;;
first.
The standard List.map method isn't defined with the label ~f. The type of List.map is ('a -> 'b) -> 'a list -> 'b list, but if you wanted to use the "~f" label, it would have to be "f:('a->'b) -> 'a list -> 'b list". If you wanted to define your own, you would have to define it as such:
let rec myMap ~f l = match l with
| [] -> []
| h::t -> (f h) :: (myMap ~f t);;
val myMap : f:('a -> 'b) -> 'a list -> 'b list = <fun>
and then you could call it like you wanted:
myMap ~f:String.length languages
Cheers!