I've just noticed the following functions in Lwt.mli:
val backtrace_bind : (exn -> exn) -> 'a t -> ('a -> 'b t) -> 'b t
val backtrace_catch : (exn -> exn) -> (unit -> 'a t) -> (exn -> 'a t) -> 'a t
val backtrace_try_bind : (exn -> exn) -> (unit -> 'a t) -> ('a -> 'b t) -> (exn -> 'b t) -> 'b t
val backtrace_finalize : (exn -> exn) -> (unit -> 'a t) -> (unit -> unit t) -> 'a t
Unfortunately they are undocumented. What do they do?
Some digging in GitHub and documentation shows that these are used internally for propagating backtraces between threads when using pa_lwt and -lwt-debug is passed to camlp4. They are also used for the same purpose by default with ppx_lwt.
The -lwt-debug option is documented on this page: http://ocsigen.org/lwt/2.5.0/manual/ (search the page for "backtrace support" to go to it).
The option to turn this off in ppx_lwt is documented here: https://ocsigen.org/lwt/dev/api/Ppx_lwt (search for -no-debug).
See this commit, which shows that these are used in the code generated by try_lwt, etc.: https://github.com/ocsigen/lwt/commit/78eee34fb6247da38a3d4ea5b7872676181d47e2
Edited: confirmed more things by looking through more code, and incorporated comment.
Related
I am writing a function that takes a function as input.
This function also takes a function as input.
I want to give labels to both those functions. I have tried:
let first (second: ((third: ('a -> 'b)) -> 'a )) : 'a =
but this gives me a syntax error "type expected" after the signature of third.
What am I doing wrong?
You have some oddly placed parentheses here, which doesn't make a whole lot of sense (hence why the compiler complains), but from your description I believe you want this:
let first (second: (third: 'a -> 'b) -> 'a) : 'a = ...
val first : ((third:'a -> 'b) -> 'a) -> 'a = <fun>
But note also that second here is still not a labeled argument, just the name that the argument will be bound to in the definition. To make it labeled, you need to prefix it with ~:
let first ~(second: (third: 'a -> 'b) -> 'a) : 'a = ...
val first : second:((third:'a -> 'b) -> 'a) -> 'a = <fun>
The difference in notation is because second is not part of the type. You could also have written this as:
let first : (second:(third:'a -> 'b) -> 'a) -> 'a = fun second -> ...
val first : (second:(third:'a -> 'b) -> 'a) -> 'a = <fun>
As a pass-time, I'm trying to implement all kinds of problems that were presented in a course (concerned with Lambda Calculus and various programming concepts) I took at the university. So, I'm trying to implement Church numerals and associated operators in OCaml (also as an exercise in OCaml).
This is the code so far:
let church_to_int n =
n (fun x -> x + 1) 0;;
let succ n s z =
s (n s z)
let zero = fun s z -> z
let int_to_church i =
let rec compounder i cont =
match i with
| 0 -> cont zero
| _ -> compounder (i - 1) (fun res -> cont (succ res))
in
compounder i (fun x -> x)
let add a b = (b succ) a
let mul a b = (b (add a)) zero
So, it seems to work, but then it breaks down. Let's consider these definitions:
let three = int_to_church 3
let four = int_to_church 4
church_to_int (add three four) // evaluates to 7
church_to_int (add four three) // throws type error - see later
I get that the error thrown has to do with the type polymorphism of the Church numerals when they're defined (see SO question), and then it's resolved after the closures are invoked once. However, I don't seem to understand why the type inconsistency error is thrown in this case:
let three = int_to_church 3
let four = int_to_church 4
church_to_int (mul three four) // throws type error - see later
Any thoughts?
The specific errors:
1.
Error: This expression has type (int -> int) -> int -> int but an expression was expected of type ((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
((((int -> int) -> int -> int) -> (int -> int) -> int -> int) ->
((int -> int) -> int -> int) -> (int -> int) -> int -> int) ->
'd
Type int is not compatible with type ('a -> 'b) -> 'c -> 'a
2.
Error: This expression has type ((((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) -> (('d -> 'd) -> 'd -> 'd) -> 'e) ->
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
(((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e
but an expression was expected of type
((((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
'e) ->
('f -> 'g -> 'g) -> 'h
The type variable 'e occurs inside
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e
Well i was a bit rusty with lambda-calculus, but after few discussions with some wise old men, i came to this answer : YES, writing that way, OCaml's type system do not allow the writing of Church numerals.
The real problem here is with your addition term :
let add a b = b succ a
wich has the following type
(((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) -> 'd -> 'e) -> 'd -> 'e
Where the arguments of add have not the same type. This is a bit sad since we naively expect the addition to be commutative.
You can easily verify this when writing :
let double a = add a a (* produces type error - the type variable occurs ... *)
This error means that you're trying to unify one type with a "bigger" type i.e that contains it (ex: unifying 'a with 'a -> 'a). OCaml does not allow that (unless if you set the -rectypes option wich allows cyclic types).
To understand better what's going on, let's add type annotations to help the typer (i'll change a bit your notations for sake of clarity):
type 'a church = ('a -> 'a) -> 'a -> 'a
let zero : 'a church = fun f x -> x
let succ n : 'a church = fun f x -> f (n f x)
Now let's go back to the add term and annotate it a bit to see what the typer has to say:
let add (a:'a church) b = a succ b (* we only annotate "a" to let the typer infer the rest *)
This produces a very odd type :
'a church church -> 'a church -> 'a church
That gets interesting: why is the first arg typed as an 'a church church?
The answer is the following : Here, a church integer is a value that takes a moving function of type 'a -> 'a (a self-map in mlahematics) that can browse a space, and an starting point ('a) that belongs to that space.
Here, if we specify that the parameter a has type 'a church, than 'a represent the space in which we can move.
Since succ, the moving function of a, operates over the church, than 'a here is it self an 'a church, thus making the parameter a an 'a church church.
This is not at all the type we wanted at the begining ... but that justifies why the type system do not allow your values three and four as both 1st and snd argument of add.
One solution can be to write add in a different way :
let add a b f x = a f (b f x)
Here, both a and b have the same moving function, and thus the same type, but you do not enjoy anymore the beautiful writing with the partial application ...
An other solution which makes you keep this beautiful writing would be to use universal types, that allow a larger kind of polymorphism:
type nat = {f:'a.('a -> 'a) -> 'a -> 'a}
(* this means “for all types ‘a” *)
let zero : nat = {
f=fun f x -> x
}
let succ n : nat = {
f= fun f x -> f (n.f f x)
}
let add (a:nat) (b:nat) = a.f succ b
let double a = add a a (* Now this has a correct type *)
let nat_to_int n =
n.f (fun x -> x + 1) 0;;
let nat_four = succ (succ (succ (succ zero)))
let eight_i = double nat_four |> nat_to_int //returns 8
But this solution is a bit more verbose than your initial one.
Hope it was clear.
If you look at the type of three, you get that:
val three : ('_a -> '_a) -> '_a -> '_a = <fun>
This is simply the value restriction at work. The value restriction is well explained here: https://realworldocaml.org/v1/en/html/imperative-programming-1.html#side-effects-and-weak-polymorphism
To solve it, In this case you can simply eta-expand the function:
let three x = int_to_church 3 x ;;
val three : ('a -> 'a) -> 'a -> 'a = <fun>
I noticed that some standard library functions are missing in my installation of OCaml (I followed the instructions for Ubuntu here).
For example, if I type
#show Hashtbl;;
in the utop toplevel, I get the following signature
module Hashtbl: sig
type ('a, 'b) t
val create : ?random:bool -> int -> ('a, 'b) t
val clear : ('a, 'b) t -> unit
val reset : ('a, 'b) t -> unit
val copy : ('a, 'b) t -> ('a, 'b) t
val add : ('a, 'b) t -> 'a -> 'b -> unit
val find : ('a, 'b) t -> 'a -> 'b
val find_all : ('a, 'b) t -> 'a -> 'b list
val mem : ('a, 'b) t -> 'a -> bool
val remove : ('a, 'b) t -> 'a -> unit
val replace : ('a, 'b) t -> 'a -> 'b -> unit
val iter : ('a -> 'b -> unit) -> ('a, 'b) t -> unit
val fold : ('a -> 'b -> 'c -> 'c) -> ('a, 'b) t -> 'c -> 'c
val length : ('a, 'b) t -> int
val randomize : unit -> unit
type statistics = {
num_bindings : int;
num_buckets : int;
max_bucket_length : int;
bucket_histogram : int array;
}
val stats : ('a, 'b) t -> statistics
module type HashedType =
sig type t val equal : t -> t -> bool val hash : t -> int end
module type S =
sig
type key
type 'a t
val create : int -> 'a t
val clear : 'a t -> unit
val reset : 'a t -> unit
val copy : 'a t -> 'a t
val add : 'a t -> key -> 'a -> unit
val remove : 'a t -> key -> unit
val find : 'a t -> key -> 'a
val find_all : 'a t -> key -> 'a list
val replace : 'a t -> key -> 'a -> unit
val mem : 'a t -> key -> bool
val iter : (key -> 'a -> unit) -> 'a t -> unit
val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
val length : 'a t -> int
val stats : 'a t -> statistics
end
module Make : functor (H : HashedType) -> sig end
module type SeededHashedType =
sig type t val equal : t -> t -> bool val hash : int -> t -> int end
module type SeededS =
sig
type key
type 'a t
val create : ?random:bool -> int -> 'a t
val clear : 'a t -> unit
val reset : 'a t -> unit
val copy : 'a t -> 'a t
val add : 'a t -> key -> 'a -> unit
val remove : 'a t -> key -> unit
val find : 'a t -> key -> 'a
val find_all : 'a t -> key -> 'a list
val replace : 'a t -> key -> 'a -> unit
val mem : 'a t -> key -> bool
val iter : (key -> 'a -> unit) -> 'a t -> unit
val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
val length : 'a t -> int
val stats : 'a t -> statistics
end
module MakeSeeded : functor (H : SeededHashedType) -> sig end
val hash : 'a -> int
val seeded_hash : int -> 'a -> int
val hash_param : int -> int -> 'a -> int
val seeded_hash_param : int -> int -> int -> 'a -> int
end
Notice the absence of Hashtbl.filter_map_inplace and Hashtbl.is_randomized, which are listed in the online documentation.
Why are the signatures different?
Where do I get the right library (or the right documentation)?
It's a version issue. filter_map_inplace appears to have been released in 4.03, is_randomized in 4.02. Ubuntu's OCaml package uses version 4.01.
You can find newer versions by using Anil Madhavapeddy's PPAs
add-apt-repository ppa:avsm/ppa
apt-get update
apt-get install ocaml ocaml-native-compilers camlp4-extra opam
(sourced from https://opam.ocaml.org/doc/Install.html)
Or once you have OPAM you can use it to install a newer version.
opam switch 4.02.1
eval `opam config env`
Please: I would like to examine a module's signature; is there a function to do this? Just typing the name of the module doesn't work:
# List ;;
Error: Unbound constructor List
In fact I want to do this for modules I define on the interactive top level.
Sorry if the answer is obvious - hard to search for this! Thanks.
The standard trick for this is to make a new module synonym:
# module Mylist = List;;
module Mylist :
sig
val length : 'a list -> int
val hd : 'a list -> 'a
val tl : 'a list -> 'a list
. . .
val sort : ('a -> 'a -> int) -> 'a list -> 'a list
val stable_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val fast_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val merge : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
end
#
Update
Since OCaml 4.02 this trick no longer works. Instead there is a toplevel directive for the purpose:
# #show_module List;;
module List :
sig
val length : 'a list -> int
val hd : 'a list -> 'a
val tl : 'a list -> 'a list
. . .
val sort : ('a -> 'a -> int) -> 'a list -> 'a list
val stable_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val fast_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val sort_uniq : ('a -> 'a -> int) -> 'a list -> 'a list
val merge : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
end
In OCaml versions >= 4.02, you can now also do this in the interactive interpreter:
# #show_module List;;
module List :
sig
val length : 'a list -> int
...
end
Or just use #show List;;
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Is someone may explain me functors. I would like to simple examples. When we should use functors?
Functors, essentially are a way to write modules in terms of other modules.
A pretty classic example is the Map.Make functor from the standard library. This functor lets you define a map with a specific key type.
Here's a trivial and rather dumb example:
module Color = struct
type t = Red | Yellow | Blue | Green | White | Black
let compare a b =
let int_of_color = function
| Red -> 0
| Yellow -> 1
| Blue -> 2
| Green -> 3
| White -> 4
| Black -> 5 in
compare (int_of_color a) (int_of_color b)
end
module ColorMap = Map.Make(Color)
Loading this in ocaml shows the signature of the generated modules:
module Color :
sig
type t = Red | Yellow | Blue | Green | White | Black
val compare : t -> t -> int
end
module ColorMap :
sig
type key = Color.t
type 'a t = 'a Map.Make(Color).t
val empty : 'a t
val is_empty : 'a t -> bool
val mem : key -> 'a t -> bool
val add : key -> 'a -> 'a t -> 'a t
val singleton : key -> 'a -> 'a t
val remove : key -> 'a t -> 'a t
val merge :
(key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
val iter : (key -> 'a -> unit) -> 'a t -> unit
val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
val for_all : (key -> 'a -> bool) -> 'a t -> bool
val exists : (key -> 'a -> bool) -> 'a t -> bool
val filter : (key -> 'a -> bool) -> 'a t -> 'a t
val partition : (key -> 'a -> bool) -> 'a t -> 'a t * 'a t
val cardinal : 'a t -> int
val bindings : 'a t -> (key * 'a) list
val min_binding : 'a t -> key * 'a
val max_binding : 'a t -> key * 'a
val choose : 'a t -> key * 'a
val split : key -> 'a t -> 'a t * 'a option * 'a t
val find : key -> 'a t -> 'a
val map : ('a -> 'b) -> 'a t -> 'b t
val mapi : (key -> 'a -> 'b) -> 'a t -> 'b t
end
The simple module ColorMap = Map.Make(Color) has created a module that implements a map where the keys are colors. It's now possible to call ColorMap.singleton Color.Red 1 and get a map of red to the number 1.
Note that the use of Map.Make worked because the passed module (Color) satisfies the requirements of the Map.Make functor. The docs say the type of the functor is module Make: functor (Ord : OrderedType) -> S with type key = Ord.t. The : OrderedType means that the input module (Color) has to be consistent (I'm sure there's a more official term) with the OrderedType module signature.
To be consistent with OrderedType the input module has to have a type t and a function compare with signature t -> t -> int. In other words there has to be a way to compare values of type t. If you look at the types reported by ocaml that's exactly what Color supplies.
When to use functors is a much more difficult question as often there are several possible designs each with their own trade-offs. But most of the time you'll use functors when a library supplies them as the recommended way of doing something.