I have made a class method, and I'd like to have this type :
unit -> (dir -> 'b)
But my actual method:
method iter () = fun x -> match x with
| Up -> if (Stack.is_empty pz) then raise Stack.Empty else if (Stack.length pz = 1) then failwith "Cannot go up" else (ignore (Stack.pop pz) ; {< a = (Stack.top pz) >})
| Down(v) -> match (Stack.top pz) with
| Noeud(o, {contents = []}) -> raise Not_found
| Noeud(o, {contents = l}) -> if mem_assoc v l then ((Stack.push (assoc v l) pz) ; {< a = (Stack.top pz) >} ) else raise Not_found
has the type unit -> dir -> 'b
How can I make it so it becomes the first type?
Here are the custom types :
type 'a arbre = Noeud of 'a option ref * (char * 'a arbre) list ref
type dir = Up | Down of char
Edit: I need this so it can comply to a certain interface, and because of the type mismatch, it won't compile.
Thanks!
This is not the problem. unit -> (dir -> 'b) and unit -> dir -> 'b are the same type in OCaml! (the type arrow is right-associative)
Could you show us the actual error message so we can know where the problem lies?
Addendum: have you actually tried this? If there is no other issue, then you'll find it'll just work.
Related
I wonder why one example fails and not the other.
(* this fails *)
(* (l fails to type check)
This expression has type 'a but an expression was expected of type
(module M.TFixU)
The module type M.TFixU would escape its scope
*)
let foldList1 (type ar) algr l =
let module M = FixT (ListIntF) in
let (module LU : M.TFixU) = l in
assert false
(* but this works *)
let foldList2 (type ar) algr l =
let (module LU : FixT(ListIntF).TFixU) = l in
assert false
complete code
module Higher = struct
type ('a, 't) app
module type NewType1 = sig
type 'a s
type t
val inj : 'a s -> ('a, t) app
val prj : ('a, t) app -> 'a s
end
module NewType1 (X : sig
type 'a t
end) =
struct
type 'a s = 'a X.t
type t
external inj : 'a s -> ('a, t) app = "%identity"
external prj : ('a, t) app -> 'a s = "%identity"
end
end
module Fix = struct
open Higher
module FixT (T : NewType1) = struct
module type T_Alg = sig
type a
val alg : (a, T.t) app -> a
end
module type TFixU = sig
module App : functor (A : T_Alg) -> sig
val res : A.a
end
end
type tFixU = (module TFixU)
end
end
module Pb = struct
open Higher
open Fix
(* intro *)
type 'r listIntF = Empty | Succ of (int * 'r)
module ListIntF = NewType1 (struct
type 'r t = 'r listIntF
end)
(* this fails *)
let foldList1 (type ar) algr l =
let module M = FixT (ListIntF) in
let (module LU : M.TFixU) = l in
(* (l fails to type check)
This expression has type 'a but an expression was expected of type
(module M.TFixU)
The module type M.TFixU would escape its scope
*)
let module T = LU.App (struct
type a = ar
let alg = algr
end) in
T.res
(* but this doesn't *)
let foldList2 (type ar) algr l =
let (module LU : FixT(ListIntF).TFixU) = l in
let module T = LU.App (struct
type a = ar
let alg = algr
end) in
T.res
end
In the first case, the type of l is unified with the type defined in the module M, which defines the module type. Since the type is introduced after the value l, which is a parameter in an eager language so it already exists, the value l receives a type that doesn't yet exist at the time of its creation. It is the soundness requirement of the OCaml type system that the value lifetime has to be enclosed with its type lifetime, or more simply each value must have a type. The simplest example is,
let x = ref None (* here `x` doesn't have a type since it is defined later *)
type foo = Foo;; (* the `foo` scope starts here *)
x := Some Foo (* foo escapes the scope as it is assigned to `x` via `foo option` *)
Another simplified example, that involves a function parameter is the following,
let foo x =
let open struct
type foo = Foo
end in
match x with
| Some Foo -> true (* again, type foo escapes the scope as it binds to `x` *)
| None -> false
A very good article that will help you understand in-depth scopes and generalization is Oleg Kiselyov's How OCaml type checker works -- or what polymorphism and garbage collection have in common.
Concerning the second case, you clearly specified the type of l using the applicative nature of OCaml functors. And since the typechecker knows that the lifetime of FixT(ListIntF).TFixU is greater than the lifetime of l it is happy.
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
I am trying to create and use a stack object (modified to have strings) from here:
let s = object
val mutable v = [""; ""]
method pop =
match v with
| hd :: tl ->
v <- tl;
Some hd
| [] -> None
method push hd =
v <- hd :: v
end ;;
let () =
s#push "first";
s#push "second";
s#push "third";
print_endline s#pop; (* error from this line *)
print_endline s#pop;
print_endline s#pop;
However, I am getting following error:
$ ocaml objects.ml
File "./objects.ml", line 19, characters 15-20:
Error: This expression has type string option
but an expression was expected of type string
I am not able to understand the error: If the expected type was string why expression of type string is not being accepted?
I am not able to understand the error: If the expected type was string why expression of type string is not being accepted?
Because the expression s#pop doesn't have type string. Its type is string option, i.e., it is either Some s or None, where s has type string.
Look at the pop method implementation, which returns Some s if there are more elements waiting in the stack, or None if the stack is empty,
method pop =
match v with
| hd :: tl ->
v <- tl;
Some hd (* returns `Some hd` *)
| [] -> None (* returns `None` *)
You can implement a helper function, that will print a value of type string option, e.g.,
let print_some s = match s with
| None -> print_endline "empty"
| Some s -> print_endline s
Here is how it is used
let () =
s#push "first";
s#push "second";
s#push "third";
print_some s#pop;
print_some s#pop;
print_some s#pop;
Here are some alternative implementations of the stack object, that use other ways to communicate to the caller that the stack is empty, e.g., a sentinel value from the stack element domain (provided by a user), an exception, or the result type, parametrized with a stringly typed error.
let stack_with_sentinel empty = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
hd
| [] -> empty
end
let stack_with_exception = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
hd
| [] -> raise Not_found
end
let stack_with_result = object
val mutable v = []
method pop = match v with
| hd :: tl ->
v <- tl;
Ok hd
| [] -> Error "empty stack"
end
There are many other ways to define it, but using the option type is the most common.
I am creating monads in OCaml and need to compose them, so I created transformers. I implemented the regular monad in terms of the transformer with the Identity monad:
module type MONAD = sig
type 'a m
val (>>=) : 'a m -> ('a -> 'b m) -> 'b m
val return : 'a -> 'a m
end
module Identity : MONAD = struct
type 'a m = 'a
let (>>=) m f = f m
let return x = x
end
module OptionT (M : MONAD) : MONAD with type 'a m := ('a option) M.m = struct
type 'a m = ('a option) M.m
let (>>=) m f = M.(>>=) m (fun option ->
match option with
| Some x -> f x
| None -> M.return None)
let return x = M.return ## Some x
end
module Option = OptionT(Identity)
However, I can't do this:
open Option
let _ = (Some 1) >>= (fun x -> Some (x + 1))
The errors are:
(Some 1)
This expression has type 'a option
but an expression was expected of type 'b option Identity.m
Some (x + 1)
This expression has type 'a option
but an expression was expected of type 'b option Identity.m
If I try to fix the error with module Identity : MONAD with type 'a m = 'a I get an error at module Option = OptionT(Identity) that states that
The type `m' is required but not provided
It seems that now, 'a has replaced 'a m in the signature.
Doing
module Option : MONAD with type 'a m := 'a option = struct
type 'a m = 'a option
let (>>=) m f =
match m with
| Some x -> f x
| None -> None
let return x = Some x
end
works just fine.
How do I tell the compiler that a module implements a signature so that a type declared in the signature is the same as another type, while still keeping the signature's original type declaration?
It seems that now, 'a has replaced 'a m in the signature.
This the effect of destructive substitution, when you write
module Identity : MONAD with type 'a m := 'a
you are asking the compiler to substitute all instance of 'a m by 'a.
Contrarily, standard with constraint adds a type equality to the module type
module Identity : MONAD with type 'a m = 'a
Looking at your various examples, it seems that you have confused the two, and are using destructive substitution when you meant to add a type constraint:
module OptionT(X:Monad) : MONAD with type 'a m = 'a = …
(* or *) module Option : MONAD with type 'a m = 'a option = …
and not
module OptionT(X:Monad) : MONAD with type 'a m := 'a = …
(* nor *) module Option : MONAD with type 'a m := 'a option = …
This expression has type 'a option but an expression was expected of type 'b option Identity.m
And indeed, the compiler does not know anything about Identity except that its signature is MONAD. (: MONAD) is not something that merely helps the compiler, it hides all information about Identity except that its signature is MONAD.
So, you can add a type equality for that
module Identity : MONAD with type 'a m = 'a = ...
and it works.
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.