Here's a minimal example out of my code demonstrating the problem:
module Substring = struct
type t = {
base: string;
pos: int;
len: int
}
end
module Parser = struct
type 'a t = Substring.t -> ('a * Substring.t) option
let return x s = Some (x, s)
end
type (_, _) t =
| TryParse : unit Parser.t -> ('a, 'a) t
| Parse : 'b Parser.t -> ('a, 'b -> 'a) t
| Concat : ('b, 'c) t * ('a, 'b) t -> ('a, 'c) t
let p = Parse (Parser.return "xxx")
My problem is that I want val p : ('a, string -> 'a) t to be polymorphic and yet OCaml makes 'a weak: val p : ('_a, string -> '_a). I'm pretty sure I'm being bitten by the value restriction here and I'm not quite sure how to get around it.
Yes, this is the value restriction. You need to eta-expand the problematic definition, like this:
let p = Parse (fun x -> Parser.return "xxx" x)
Annoying, isn't it?
If you want a binding to be polymorphic then you usually have to ensure that it is a "syntactic value". An expression containing a partial application doesn't qualify (because in general partial applications may have an effect), but a (fun ...) is fine.
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>
It seems that only a * b can fit in to _ and only (a,b) can fit in to (a,_).
I can imagine that a*b is a proper type for the internal product with components a and b whereas (a,b) is a external product of type a and type b (just a guess)
But are there examples distinguishing the two ?
type zero = Z : zero
type 'a succ = S : 'a succ
type _ ptree1 =
| Leaf : 'a -> ('a * zero) ptree1
| Node : (('a * 'n) ptree1 * ('a * 'n) ptree1) -> ('a * 'n succ) ptree1
type (_, _) ptree =
| Leaf : 'a -> ('a, zero) ptree
| Node : (('a, 'n) ptree * ('a, 'n) ptree) -> ('a, 'n succ) ptree
(* bad
type ('a * _) ptree =
| Leaf : 'a -> ('a, zero) ptree
| Node : (('a, 'n) ptree * ('a, 'n) ptree) -> ('a, 'n succ) ptree
*)
let rec last1 : type n a. (a * n) ptree1 -> a = function
| Leaf x -> x
| Node (_, t) -> last1 t
let rec last : type n a. (a, n) ptree -> a = function
| Leaf x -> x
| Node (_, t) -> last t
Type constructors have an arity in OCaml.
For instance, in
type ('a,'b) either =
| Left of 'a
| Right of 'b
the type constructor either has an arity of two. And ('a,'b) either denotes the type constructor either applied to two argument 'a and 'b. The form ('a,'b) does not exist by itself in the language.
However, it is possible to encode type constructor with an arity of n as a type constructor of arity 1 constrained on only having a n-tuple type as an argument.
Typically, this means rewriting either to
type 'p either2 =
| Left2 of 'a
| Right2 of 'b
constraint 'p = 'a * 'b
let translation: type a b. (a*b) either2 -> (a,b) either = function
| Left2 x -> Left x
| Right2 x -> Right x
Here, either2 is a type constructor of arity one, but which arguments must be a 2-tuple type.
This is the equivalent of translating a function of type 'a -> 'b -> 'c to a function of type 'a * 'b -> 'c at the type-level.
And another point of view is that type-level applications were written like function applications ('a,'b) either would be written either 'a 'b and ('a * 'b) either2 would become either2 ('a * 'b).
Without GADTs, this kind of encoding requires the use of an explicit constraint and they are thus not that frequent.
With GADTs, since the definition of the GADTs is free to construct its own type indices, this choice is simply more apparent. For instance, one can define an eccentric version of either as
type (_,_,_) either3 =
| Left3: 'a -> ('a list -> _, 'a * unit, _) either3
| Right3: 'a -> ( _ -> 'a array, _, unit * 'a) either3
let translate: type a b. (a list -> b array, a * unit, unit * b) either3 -> (a,b) either =
function
| Left3 x -> Left x
| Right3 x -> Right x
Here, either3 is a type constructor of arity 3, which stores the left and right types all over the place among its 3 argument.
I want to print a list with different element in it (for educational purpose)
I have read a tutorial that explain how to store different type in list.
type _ list =
[] : unit list
| ( :: ) : 'b * 'a list -> ('b ->'a) list;;
1 :: "e" :: 'r' :: [];; (* this is allowed *)
how I can do something like this pseudo-code:
match typeof(my_expr) with
int -> print_int
| string -> print_string
we will have "1,e,r" printed.
Some solutions i have searched
Change my type in text and printing it
Use a different type definition maybe ('a, 'b) list ?
I ask this because the OCaml toplevel know the type of every variable and show always the type in the right format: can I call this printer ?
Is there a solution only for toplevel that we can install with the #install_printer ?
I know that compiler discard type's info after the type checking pass.
The printer of the toplevel should work fine:
[1; "one"; 1.];;
- : (int -> string -> float -> unit) list =
(::) (1, (::) ("one", (::) (1., [])))
(The unoptimal printing is an unfortunate consequence of ensuring that values printed by the toplevel can be copy-pasted back to the top-level and yields the same value)
But this is only possible outside of the language itself: the toplevel printers can inspect the typing environment which is purposefully not possible in the language itself. Indeed functions like typeof would break parametricity. There is thus no universal printer function in OCaml (without looking at the internal memory representation) and no universal heterogeneous list printer.
If you want to print an heterogeneous list, there are three possible paths:
print a specific type of the heterogeneous list
let print_concrete ppf (x::y::z::rest) = Format.fprintf ppf "%f %f %f" x y z
(Contrary to appearance, this function is total: its type makes it impossible to use on lists with fewer than three elements)
Use heterogeneous lists that always pack a printing function along its main value
type 'a printer = Format.formatter -> 'a -> unit
type _ showable_list =
| [] : unit showable_list
| (::):
('a * 'a printer) * 'b showable_list
-> ('a -> 'b) showable_list
let rec print: type a. a showable_list printer =
fun ppf l -> match l with
| [] -> ()
| (a,printer) :: rest -> Format.fprintf ppf "%a# %a" printer a print rest
provide a matching heterogeneous list of printing functions
type 'a plist =
| []: unit plist
| (::): 'a printer * 'b plist -> ('a -> 'b) plist
let rec print: type l. l plist -> l list printer = fun printers ppf values ->
match printers, values with
| [], [] -> ()
| p :: prest, a :: rest -> Format.fprintf ppf "%a# %a" p a (print prest) rest
The fact that you often need to specialize the heterogeneous list type may make it worthwhile to introduce a functor for generating them:
module Hlist(Specialization: sig type 'a t end) = struct
open Specialization
type 'a list =
| []: unit list
| (::): 'a t * 'b list -> ('a -> 'b) list
end
then the previous specialized type can be constructed with
module Showable_list = Hlist(struct type 'a t = 'a * 'a printer end)
module Printer_list = Hlist (struct type 'a t = 'a printer end)
Hello I am getting ready for my finals and there is always ml type inference on the exams .
i.e. we are asked to write the type of a function like this one :
fun ugh x y z = x z (y z);
val ugh = fn : ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c
or
fun doh x y z = z (x y ) (y + 1);
val doh = fn : (int -> 'a) -> int -> ('a -> int -> 'b) -> 'b
However all the ways I am trying to infer the type I always get it wrong .
Although there are examples online there are no examples for functions like that .
Is there a way to make up the type following some guidelines ?
The guidelines would be best if applied to the first example .
Yes, there are several examples of type inference by hand on StackOverflow: 1, 2, 3, 4, 5, ...
To infer the type of fun ugh x y z = x z (y z), you could start by saying that
val ugh : 'a -> 'b -> 'c -> 'd
since it takes three curried arguments. You can also see that x : 'a is a function of two curried parameters and that y : 'b is a function of one parameter, and that 'd should be expressed entirely in terms of 'a, 'b and 'c.
So for the type of y, set 'b = 'c -> 'e, since it takes z : 'c as input and returns something of a type that we haven't gotten to yet.
And for the type of x, set 'a = 'c -> 'e -> 'f, since it takes z : 'c and the output of y as input and returns something of a type that we haven't gotten to yet.
Replacing those, adding parentheses as needed, you get
val ugh : ('c -> 'e -> 'f) -> ('c -> 'e) -> 'c -> 'f
At that point you might want to rename them so you get
val ugh : ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c
but you don't really have to.
The only things I had to think about here was the fact that the type of x depends on the type of y, so I wanted to determine that first.
To infer the type of fun doh x y z = z (x y) (y + 1), you could similarly start by saying that
val doh : 'a -> 'b -> 'c -> 'd
since it also takes three curried arguments. Most easily you can set 'b = int, and similar to the first example, you can set 'a = int -> 'e and then 'c = 'e -> int -> 'd.
Replacing those, adding parentheses as needed, you get
val doh : (int -> 'e) -> int -> ('e -> int -> 'd) -> 'd
or after a little renaming
val doh : (int -> 'a) -> int -> ('a -> int -> 'b) -> 'b
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>