1) Is there a way to type this? 2) Anyone able to expound on these error messages?
let identity1: 'a => 'a = [%bs.raw {|
function(value) {
return value
}
|}];
/*
Line 2, 11: The type of this expression, '_a -> '_a, contains type variables that cannot be generalized
*/
let identity2: 'a. 'a => 'a = [%bs.raw {|
function(value) {
return value
}
|}];
/*
Line 8, 11: This definition has type 'a -> 'a which is less general than 'a0. 'a0 -> 'a0
*/
bs.raw
is effectful (expansive to be precise), therefore it is subject to the value restriction:
http://caml.inria.fr/pub/docs/manual-ocaml/polymorphism.html#sec51 .
In brief, the type of the result of a function application cannot be generalized, because it may have captured some hidden references. For instance, consider the function:
let fake_id () = let store = ref None in fun y ->
match !store with
| None -> y
| Some x -> store := Some x; y
let not_id = fake_id ()
let x = not_id 3
then the next application of not_id
will be 3
. Therefore the type of not_id
cannot be ∀'a. 'a -> 'a
. That's why, the type-checker infers for your function the type '_weak1 -> '_weak1
(using 4.06 notation). This type _weak1
is not a polymorphic type but a placeholder for a yet unknown concrete type.
In a normal setting, the solution is to make not_id
a value with η-expansion:
let id x = fake_id () x
(* or *)
let id: 'a. 'a -> 'a = fun x -> fake_id () x