OCaml: circularity between variant type and module definition - module

I'm switching from Haskell to OCaml but I'm having some problems. For instance, I need a type definition for regular expressions. I do so with:
type re = EmptySet
| EmptyWord
| Symb of char
| Star of re
| Conc of re list
| Or of (RegExpSet.t * bool) ;;
The elements inside the Or are in a set (RegExpSet), so I define it next (and also a map function):
module RegExpOrder : Set.OrderedType =
struct
let compare = Pervasives.compare
type t = re
end
module RegExpSet = Set.Make( RegExpOrder )
module RegExpMap = Map.Make( RegExpOrder )
However, when I do "ocaml [name of file]" I get:
Error: Unbound module RegExpSet
in the line of "Or" in the definition of "re".
If I swap these definitions, that is, if I write the modules definitions before the re type definitions I obviously get:
Error: Unbound type constructor re
in the line of "type t = re".
How can I solve this?
Thanks!

You can try to use recursive modules. For instance, the following compiles:
module rec M :
sig type re = EmptySet
| EmptyWord
| Symb of char
| Star of re
| Conc of re list
| Or of (RegExpSet.t * bool)
end =
struct
type re = EmptySet
| EmptyWord
| Symb of char
| Star of re
| Conc of re list
| Or of (RegExpSet.t * bool) ;;
end
and RegExpOrder : Set.OrderedType =
struct
let compare = Pervasives.compare
type t = M.re
end
and RegExpSet : (Set.S with type elt = M.re) = Set.Make( RegExpOrder )

Related

recursive module as a fix point in OCaml

Is it possible to write the module Nat as a fixpoint or a universal algebra for some functor NatF ?
module rec Nat : sig
type t = Z | S of Nat.t
end = struct
type t = Z | S of Nat.t
end
Presumably to_int would then be a regular fold
let rec to_int : Nat.t -> int = function Z -> 0 | S x -> 1 + to_int x
I am not sure that I fully understand your question, but it looks like that you want to define a fixed-point combinator on the type level, so that you can write,
module NatF = Fix(functor (F : F)(T:T) -> struct
type t = Z | S of F(T).t
end)
module R = NatF(struct type s type t = Z | S of s end)
It is possible, e.g.,
module type T = sig type t end
module type F = functor (T : T) -> T
module type F2F = functor (F : F) -> F
module type Fix = functor (F : F2F) -> F
module rec Fix : Fix = functor (F : F2F) -> F (Fix(F))
but the problem is that it will leave the resulting type R.t abstract, so you can't write the to_int function over R.t. Even if you will try to define the to_int function inside of the open-recursive functor, you won't be able to recurse over the F(T).t type of the S branch as it will be abstract.
So, I believe, that in the end, you will still have to rely either on the recursion that is implicit in the type definition or on recursive modules to tighten up the fixed point, e.g.,
module type T = sig type t end
module Nat (T : T) = struct
module type S = sig
type t = Z | S of T.t
end
end
module type F = functor (T : T) -> Nat(T).S
module type F2F = functor (F : F) -> F
module type Fix = functor (F : F2F) -> F
module rec Fix : Fix = functor (F : F2F) -> F (Fix(F))
module F = functor(F : F)(T : T) -> struct
type t = F(T).t = Z | S of T.t
end
module rec R : sig
type t = Z | S of R.t
end = Fix(F)(R)
rephrasing Ivg's answer and its issue (with a tweak to make it compile - interesting to understand "safe module")
module Ivg = struct
module type T = sig type t end
module type F = functor (T : T) -> T
module NatF (T : T) = struct
type t = Z | S of T.t
end
module type Fix = functor (F : F) -> T
module rec Fix : Fix =
functor (F : F) -> F (struct type t = Fix(F).t end) (*tweak - prevent loop at definition - cf "safe module" at https://caml.inria.fr/pub/papers/xleroy-recursive_modules-03.pdf *)
module Nat = Fix (NatF)
(* As mentioned by #ivg :
it will leave the resulting type Nat.t abstract,
so you can't write the to_int function over Nat.t.
Even if you will try to define the to_int function inside of the open-recursive functor,
you won't be able to recurse over the F(T).t type of the S branch as it will be abstract. *)
end
Whose solution can be approximated by
module type T = sig type t end
module type F = functor (T : T) -> T
module rec NatF : F =
functor (T : T) ->
struct
type t = Z | S of T.t
end
and FixedNat : T = struct
type t = NatF(FixedNat).t
end
Fix now statically know it is being applied to NatF.
But T is still abstract
I don't know any other way as of yet (modular implicit ?)
Another way of expressing Nat
(* type 't natF = Z | S of 't *)
module rec FixedNat : sig
module type Z = sig end
module type S = sig
val n : FixedNat.n
end
type n = Z | S of (module S)
end =
FixedNat
let rec to_int : FixedNat.n -> int = function
| Z -> 0
| S (module N) -> to_int N.n
which still does not express FixedNat as an explicit fix point of an algebra
Another approximate solution.
The encoding of modules fixed point can be done through its universal property for type level algebras
module Algebras = struct
(* type level natf_algebra : 'a natF -> 'a *)
module type natF_algebra = sig
type a
val zero : a
val succ : a -> a
end
(* A type level algebra lowered *)
type 'a natF_algebra = (module natF_algebra with type a = 'a)
(* is an ordinary value level algebra *)
type 'a natf = Z | S of 'a
type 'a natf_algebra = { alg : 'a natf -> 'a }
end
module Encoding = struct
open Algebras
(* Universal encoding *)
module type NatU = sig
module Ap : functor (F : natF_algebra) -> sig
val res : F.a
end
end
type natU = (module NatU)
(* recursive module *)
module rec FixedNat : sig
module type Z = sig end
module type S = sig
val n : FixedNat.n
end
type n = Z | S of (module S)
end =
FixedNat
end
module Equivalence = struct
open Algebras
open Encoding
let fixedNat_to_natU : FixedNat.n -> natU =
fun n ->
(module struct
module Ap (F : natF_algebra) = struct
let rec foldNat = function
| FixedNat.Z -> F.zero
| FixedNat.S (module N) -> foldNat N.n |> F.succ
let res = foldNat n
end
end)
let rec natU_to_fixedNat : natU -> FixedNat.n =
fun (module N) ->
let module M = N.Ap (struct
type a = FixedNat.n
let zero = FixedNat.Z
let succ x =
FixedNat.S
(module struct
let n = x
end)
end) in
M.res
end

Match inside match - ocaml raises syntax error

Does anyone know why this function raises the syntax error? I haven't provided my written side functions, since they are probably not that relevant here, since it's revolving around proper syntax.
I tried deleting the brackets that raised the error (which I think.. should be there?), only to then raise another syntax error one line lower, at the begining of the row with the line "|".
type 'a grid = 'a Array.t Array.t
type problem = { initial_grid : int option grid }
type available = { loc : int * int; possible : int list }
type state = { problem : problem; current_grid : int option grid; available = available list }
let branch_state (state : state) : (state * state) option =
if prazni_kvadratki state.current_grid = [] then
None
else
let lst = prazni_kvadratki state.current_grid in
let loc = List.hd lst in
let st1_grid = copy_grid state.current_grid in
let st2_grid = copy_grid state.current_grid in
match razpolozljive state.current_grid loc with
| x :: xs -> (vstavi_vrednost st1_grid loc (Some x);
let st1 = {problem = state.problem; current_grid = st1_grid} in
match xs with
| [y] -> (vstavi_vrednost st2_grid loc (Some y);
let st2 = {
problem = state.problem;
current_grid = st2_grid
}) (* this is where it shows me a syntax error*)
| y :: ys -> let st2 = {
problem = state.problem;
current_grid = copy_grid state.current_grid;
available = {loc = loc; possible = xs}
})
Some (st1, st2)
On around the 5th last line or so you have let with no matching in. The let expression always must have an in.
The basic rule for nested match is that you should use parentheses or begin/end around the inner one:
match x with
| [] -> 0
| [_] ->
begin
match y with
| [] -> 1
| _ -> 2
end
| _ -> 3
Otherwise the final cases of the outer match look like they belong to the inner one. I don't think this is your problem here because you have no outer cases after the inner match.
Syntax issues
You have a few syntax issues.
type state = { problem : problem; current_grid : int option grid; available = available list }
You likely meant to have:
type state = { problem : problem; current_grid : int option grid; available : available list }
However, given how you construct values later in your program where you provide a value for the available field in one case but not in the other, you may want a variant type that allows your state type to be constructed with or without this value, with distinct behavior when not constructed with this value. This might look like:
type state =
| With_available of { problem : problem;
current_grid : int option grid;
available : available list }
| Without_available of { problem : problem;
current_grid : int option grid }
The other syntax issue is missing an in to go with a let which brings us to:
Scoping issues
There are clearly some miunderstandings here for you in regards to how scope works with let bindings in OCaml.
Aside from a definition at the topmost level of a program, all let bindings are local bindings. That is, they apply to a single expression that trails an in keyword.
Consider this toplevel session.
# let x = 5;;
val x : int = 5
# let y =
let x = 42 in
x + 3;;
val y : int = 45
# x;;
- : int = 5
#
Here the x bound with let x = 42 in x + 3 is only in scope for the duration of the expression x + 3. Once we're done with that expression, that binding for x is gone. In the outer scope, x is still bound to 5.
In both cases in your match you bind names st1 and st2, which would have to be local bindings, but then you try to use them in an outer scope, where they don't exist.
If you want st1 and st2, you'd need to bind them in a similar way to a and b in the below simple example.
# let (a, b) = match [1; 2; 3] with
| [x] -> (x, x)
| x :: y :: _ -> (x, y)
| _ -> (1, 1)
in
a + b;;
- : int = 3
#
Pattern-matching
Please also note that the pattern-matching you're shown is not exhaustive. It does not handle an empty list. If you consider it impossible that an empty list will be a result, you still have to either handle it anyway or use a different data structure than a list which can by definition be empty.
You've shown pattern-matching of the basic pattern:
match some_list with
| x :: xs ->
match xs with
| [y] -> ...
| y :: xs -> ...
We can actually match against the two possibilities you've show in one level of match.
match some_list with
| x :: [y] -> ...
| x :: y :: ys -> ...
If you still need to address y :: ys as xs in the second case, we can readily bind that name with the as keyword.
match some_list with
| x :: [y] -> ...
| x :: (y :: ys as xs) -> ...

OCaml syntax error in functor

I'm trying to create a functor that makes a polynomial ring out of a ring. My underlying type, Ring_elt, has the following signature:
module type Ring_elt = sig
type t
val add : t -> t -> t
val mul : t -> t -> t
val zer : t
val one : t
val neg : t -> t
end;;
My polynomial functor looks like:
module Make_Poly2(Underlying:Ring_elt) = struct
type t = Poly of Underlying.t list
let rec create lst =
match List.rev lst with
| Underlying.zer :: tl -> create List.rev tl
| _ -> Poly of lst
end;;
(so the 'create' function should take a list, remove the leading zeros, and then return the polynomial of the result). However, I get a syntax error and utop underlines the "zer" after "Underlying."
By comparison, the following code (for making integer polynomials) works:
module Make_int_poly = struct
type t = Poly of int list
let rec create lst =
match List.rev lst with
| 0 :: tl -> create (List.rev tl)
| _ -> Poly lst
end;;
Any idea what's going on?
An OCaml pattern is built from constants, data constructors, and new names bound by the pattern match. Underlying.zer isn't any of those things. But 0 is one of them.
Seems like you can just use an if to compare against Underlying.zer.
Jeffrey's answer is good but instead of correcting it with an if construction, what you should do is the following : use algebraic data types
Instead of writing
val zer : t
val one : t
You could write
module type Ring_elt = sig
type t = Zer | One | Num of t
val add : t -> t -> t
val mul : t -> t -> t
val neg : t -> t
end
module Make_int_poly = struct
type t = Poly of int list
let rec create lst =
match List.rev lst with
| Underlying.Zer :: tl -> create (List.rev tl)
| _ -> Poly lst
end
It's a much better way of doing it since you can easily pattern match on it and even add some constants to your type t without problems.

Dealing with type name conflicts when include'ing two modules in OCaml

can anyone help me for the exercise 12.5 of Jason Hickey's book?
Basically, the question is how to avoid the following conflicting issue due to "include" in practice? Thanks.
# module type XSig = sig
type t
val x : t
end;;
# module A : XSig = struct
type t = int
let x = 0
end;;
# module B : XSig = struct
type t = int
let x = 1
end;;
# module C = struct
include A
include B
end;;
I don't know what the question precisely says, but regarding your code snippet, there are various very different way to interpret what you're trying to do.
What you are currently doing is sealing A and B under two abstract, incompatible signatures, then trying to mix them in a module, only to have a name conflict.
Maybe you just want to avoid the name conflict. The simplest solution, of course, is not to use the same names for both types A.t and B.t. Then you can "not include B":
module C = struct
include A
let x_b = B.x
end
The better solution is to use OCaml 3.12 destructive substitution for signatures, with type t := foo, to mask the type t from the module B:
module C = struct
include A
type u = B.t (* rename B.t into 'u' to avoid name conflict *)
include (B : XSig with type t := u) (* replaces 't' by 'u' *)
end
You may also want the types for modules A and B to be compatible. In this case you must not seal them with abstract types.
module type XSig = sig
type t
val x : t
end
module A = struct
type t = int
let x = 0
end
(* if you want to check that A can be sealed by XSig, do it here,
outside the main declaration *)
let _ = (module A : XSig)
module B = struct
type t = int
let x = 1
end
module C = struct
include (A : XSig with type t := int)
include (B : XSig with type t := int)
end
(* module C : sig
val x = int
end *)
In this example both types A.t and B.t are removed by the destructive subtitution :=. If you want your module C to have a type t, you can write either of:
module C = struct
type t = int
include (A : XSig with type t := t)
include (B : XSig with type t := t)
end
or, using non-destructive substitution (changes the type definition instead of removing it):
module C = struct
include (A : XSig with type t = int)
include (B : XSig with type t := t)
end
See the manual page for destructive substitution type type t := ... for more details, and the one on the classic with type t = ... construction for comparison.

Recursive Set in OCaml

how can I manage to define a Set in OCaml that can contains element of its type too?
To explain the problem I have a type declaration for a lot of data types like
type value =
Nil
| Int of int
| Float of float
| Complex of Complex.t
| String of string
| Regexp of regexp
| Char of char
| Bool of bool
| Range of (int*int) list
| Tuple of value array
| Lambda of code
| Set of ValueSet.t (* this isn't allowed in my case since module is declared later*)
In addition I declare a concrete module for ValueSet later in the same file:
module ValueSet = Set.Make(struct type t = value let compare = Pervasives.compare end)
The problem is that ValueSet has value as it's elt type but value can be a ValueSet so I'm getting troubles while trying to compile it.
All of these declarations are contained in just a file named types.ml (that has it's own interface types.mli but without any ValueSet module decl since I'm not either sure it's possible).
Can this problem be solved in some way?
You can use recursive modules. Language manual uses precisely the same example of recursive set type to illustrate this language feature. Below is a relevant excerpt.
A typical example of a recursive module definition is:
module rec A : sig
type t = Leaf of string | Node of ASet.t
val compare: t -> t -> int
end
= struct
type t = Leaf of string | Node of ASet.t
let compare t1 t2 =
match (t1, t2) with
(Leaf s1, Leaf s2) -> Pervasives.compare s1 s2
| (Leaf _, Node _) -> 1
| (Node _, Leaf _) -> -1
| (Node n1, Node n2) -> ASet.compare n1 n2
end
and ASet : Set.S with type elt = A.t
= Set.Make(A)
It can be given the following specification:
module rec A : sig
type t = Leaf of string | Node of ASet.t
val compare: t -> t -> int
end
and ASet : Set.S with type elt = A.t