ocaml + oasis + custom module, how to compile - ocaml

So i have the following files:
_oasis:
OASISFormat: 0.4
Name: PongBattleServer
Version: 0.1.0
Synopsis: Server for handling multi-player pong games
Authors: Jason Miesionczek
License: MIT
Plugins: META (0.4), DevFiles (0.4)
Executable pongserver
Path: src
BuildTools: ocamlbuild
MainIs: main.ml
main.ml:
open Players;;
let () =
let mgr = new player_manager
players.ml:
type player =
{
name: string;
score: int;
}
class player_manager =
object (self)
val mutable player_list = ( [] : player list)
method add p =
player_list <- p :: player_list
end;;
when i run make i get this error:
ocaml setup.ml -build
/home/araxia/.opam/system/bin/ocamlfind ocamldep -modules src/main.ml > src/main.ml.depends
+ /home/araxia/.opam/system/bin/ocamlfind ocamldep -modules src/main.ml > src/main.ml.depends
File "src/main.ml", line 4, characters 32-32:
Error: Syntax error
Command exited with code 2.
E: Failure("Command ''/usr/bin/ocamlbuild' src/main.byte -tag debug' terminated with error code 10")
make: *** [build] Error 1
Makefile:7: recipe for target 'build' failed
i am new to ocaml and oasis, etc. what am i doing wrong?

This has nothing to do with Oasis or whatsoever, it's just when you write
let () =
let mgr = new player_manager
OCaml expects an in keyword because either let introduces a global variable either it introduces a local variable and then you'll need a let var = expr in expr, nothing else.
So, replace it by
let () =
let mgr = new player_manager in ()
for now because you aren't doing anything with mgr.

Related

Unhandled Exception with OCaml 5.0.0~beta1

I'm inconsistently getting this error in a first experiment with OCaml 5.0.0~beta1:
Fatal error: exception Stdlib.Effect.Unhandled(Domainslib__Task.Wait(_, _))
My setup:
Processor: Intel(R) Core(TM) i7-8750H CPU # 2.20GHz
Debian 10 (buster)
opam version 2.1.3 installed as binary from this script
opam switch: "→ 5.0.0~beta1 ocaml-base-compiler.5.0.0~beta1 5.0.0~beta1"
After a quick read of this tutorial, I copied the parallel_matrix_multiply function and added some code in the end just to use it:
open Domainslib
let parallel_matrix_multiply pool a b =
let i_n = Array.length a in
let j_n = Array.length b.(0) in
let k_n = Array.length b in
let res = Array.make_matrix i_n j_n 0 in
Task.parallel_for pool ~start:0 ~finish:(i_n - 1) ~body:(fun i ->
for j = 0 to j_n - 1 do
for k = 0 to k_n - 1 do
res.(i).(j) <- res.(i).(j) + a.(i).(k) * b.(k).(j)
done
done);
res ;;
let pool = Task.setup_pool ~num_domains:3 () in
let a = Array.make_matrix 2 2 1 in
let b = Array.make_matrix 2 2 2 in
let c = parallel_matrix_multiply pool a b in
for i = 0 to 1 do
for j = 0 to 1 do
Printf.printf "%d " c.(i).(j)
done;
print_char '\n'
done;;
I then compile it with no errors with
ocamlfind ocamlopt -linkpkg -package domainslib parallel_for.ml
and then comes the problem: executing the generated a.out file sometimes (rarely) prints the expected output
4 4
4 4
but usually ends with the error mentioned earlier:
Fatal error: exception Stdlib.Effect.Unhandled(Domainslib__Task.Wait(_, _))
Sorry if I am making some trivial mistake, but I can't understand what is going on, especially given that the error happens inconsistently.
The parallel_matrix_multiply computation is running outside of the Domainslib scheduler, thus whenever a task yields to the scheduler, the Wait effect is unhandled and transformed into a Effect.Unhandled exception.
The solution is to run the parallel computation within Task.run:
...
let c = Task.run pool (fun () -> parallel_matrix_multiply pool a b) in
...

Core.Command.run : API changed between v0.14 and v0.15?

The following code that was compiling successfully with Core v0.14 (ocaml 4.10), but fails with v0.15 (ocaml 4.11).
open Core;;
let command = Command.basic ~summary:"essai" (
let open Command.Let_syntax in
let%map_open s = anon(sequence ("n" %: int)) in
fun () ->
List.iter s ~f:(fun x -> Printf.printf "n = %d\n" x ) ;
)
let () = Command.run ~version:"0.0" ~build_info:"RWO" command;;
The error (with 4.11) :
File "cli.ml", line 10, characters 9-20:
10 | let () = Command.run ~version:"0.0" ~build_info:"RWO" command;;
^^^^^^^^^^^
Error (alert deprecated): Core.Command.run
[since 2021-03] Use [Command_unix]
File "cli.ml", line 10, characters 9-20:
10 | let () = Command.run ~version:"0.0" ~build_info:"RWO" command;;
^^^^^^^^^^^
Error: This expression has type [ `Use_Command_unix ]
This is not a function; it cannot be applied.
The documentation of Core.Command.run states that it is obsolete - but I fail to find how to replace it.
I think you're looking for Command_unix as indicated by the message you received. Documentation link for Command_unix.run.
The core library has been restructured in version 0.15: Unix-specific modules and functions have been moved to the core_unix library in order to make the main core library more portable (or at least javascript compatible).
The function Command_unix.run in core_unix library is exactly the same as the Command.run function in previous versions of the core library.

How to satisfy module type including polymorphic set

I am trying to create a module that exposes a set without exposing the type of the elements in the set. Here is a simplified version:
open Core
module type M_t = sig
module Id : Comparator.S
val set : (Id.t, Id.comparator_witness) Set_intf.Tree.t
end
module M : M_t = struct
module Id = Int
module S = Set.Make (Id)
let set = S.empty
end
With this signature, client applications could use the M_t signature and not know that under the hood, set contains ints. Not only is my implementation not particularly idiomatic, but it doesn't compile:
❯ dune build
File "hello_world.ml", lines 9-14, characters 17-3:
9 | .................struct
10 | module Id = Int
11 | module S = Set.Make (Id)
12 |
13 | let set = S.empty
14 | end
Error: Signature mismatch:
...
Values do not match:
val set : S.t
is not included in
val set : (int, Id.comparator_witness) Set_intf.Tree.t
File "hello_world.ml", line 6, characters 2-57: Expected declaration
File "hello_world.ml", line 13, characters 6-9: Actual declaration
I have found everal similar questions but I haven't succeeded in transferring the answers to my setting, so I apologize if this is a duplicate.
The solution I could come up with is the following:
open Core
module type M_t = sig
module Id : Comparator.S
module S : Set.S with type Elt.t = Id.t
val set : S.t
end
module M : M_t = struct
module Id = Int
module S = Set.Make (Id)
let set = S.empty
end
The thing is I couldn't find a way to force Elt.comparator_witness to be equal to Id.comparator_witness and this is the closest working solution I got to correspond to your initial problem (I'm not a Core user).

Is it possible to define an exception inside a function

One way to implement "early returns" in OCaml is via exceptions:
exception Exit
let myfunc () =
try
for i = 0 to .... do
if .. then raise Exit
done; false
with Exit -> true
However, is there a way to declare this Exit exception in the body of the function, so its name is not visible to other functions in the module?
(* I would like to do this, but it gives a syntax error *)
let myfunc () =
exception Exit
try
for i = 0 to .... do
if .. then raise Exit
done; false
with Exit -> true
Yes, what you want is possible by using a local module:
let myfunc () =
let module M = struct exception Exit end in
try
for i = 0 to 3 do
if true then raise M.Exit
done; false
with M.Exit -> true
That style is not particularly pleasant to read, though, so I wouldn't recommend it. It is enough to omit showing Exit at the next module interface if you want to hide it from most of the rest of the program.

Error while using Z3 module in OCaml

I am new to OCaml. I installed Z3 module as mentioned in this link
I am calling Z3 using the command:
ocamlc -custom -o ml_example.byte -I ~/Downloads/z3-unstable/build/api/ml -cclib "-L ~/Downloads/z3-unstable/build/ -lz3" nums.cma z3ml.cma $1
where $1 is replaced with file name.
type loc = int
type var = string
type exp =
| Mul of int * exp
| Add of exp * exp
| Sub of exp * exp
| Const of int
| Var of var
type formula =
| Eq of exp * exp
| Geq of exp
| Gt of exp
type stmt =
| Assign of var * exp
| Assume of formula
type transition = loc * stmt * loc
module OrdVar =
struct
type t = var
let compare = Pervasives.compare
end
module VarSets = Set.Make( OrdVar )
type vars = VarSets.t
module OrdTrans =
struct
type t = transition
let compare = Pervasives.compare
end
module TransitionSets = Set.Make( OrdTrans )
type transitionSet = TransitionSets.t
type program = vars * loc * transitionSet * loc
let ex1 () : program =
let vset = VarSets.empty in
let vset = VarSets.add "x" vset in
let vset = VarSets.add "y" vset in
let vset = VarSets.add "z" vset in
let ts = TransitionSets.empty in
(* 0 X' = X + 1 *)
let stmt1 = Assign( "x", Add( Var("x"), Const(1) ) ) in
let tr1 = (0,stmt1,1) in
let ts = TransitionSets.add tr1 ts in
(vset,0,ts,10)
In the above code I am defining some types. Now if I include the command "open Z3", I am getting "Error: Unbound module Set.Make".
I could run test code which uses Z3 module with out any difficulty, but unable to run with the above code.
The error message in this case is a little bit confusing. The problem is that Z3 also provides a module called Set, which doesn't have a make function. This can be overcome simply by not importing everything from Z3, as there are a number of modulse that might clash with others. For example,
open Z3.Expr
open Z3.Boolean
will work fine and opens only the Z3.Expr and Z3.Boolean modules, but not the Z3.Set module. so that we can write an example function:
let myfun (ctx:Z3.context) (args:expr list) =
mk_and ctx args
If Z3.Boolean is not opened, we would have to write Z3.Boolean.mk_and instead, and similarly we can still access Z3's Set module functions by prefixing them with Z3.Set.