Hi !
I’m still struggling with some dark parts of the type system in OCaml.
In particular, I am trying to model a specific kind of delayed computation, and I’m encountering some issues with unbound types getting out of scope. I am guessing there’s a way of fixing it but I can’t find it.
Here’ s a very simplified version of what I’m trying to do :
type 'a t =
| Done : 'a -> 'a t
| Delayed : (unit -> 'a t) -> 'a t
| Chained : 'a t * ('a -> 'b t) -> 'b t
This type would come with the proper functions :
let return x = Done x
let delay f = Delayed f
let bind x f = Chained (x, f)
let (let*) = bind
That would let me do something like
let five : int t =
let* three =
delay (fun () ->
let y = 1 in
let z = 2 in
delay (fun () -> return (y + z)))
in
return (three + 2)
and then a function that is called resolve
and lets me do something like
let x : int = resolve five (* x is the int 5 *)
However, the implementation of resolve is not compiling :
let rec resolve : 'a t -> 'a = function
| Done x -> x
| Delayed f -> resolve (f ())
| Chained (x, f) -> resolve (f (resolve x))
because
File "bin/test.ml", line 9, characters 42-43:
9 | | Chained (x, f) -> resolve (f (resolve x))
^
Error: This expression has type $Chained_'a t
but an expression was expected of type 'a t
The type constructor $Chained_'a would escape its scope
This is disturbing to me because it is not the first time that I try hiding internal types and I have made it work in the past. For example :
type packedPP = PP : ((('a, Format.formatter, unit) format -> 'a) -> unit) -> packedPP
let pf fmt (PP msgf) = Format.fprintf fmt |> msgf
let msgf = PP (fun m -> m "aa %d" 4)
let () = pf Format.std_formatter msgf
It compiles and properly show “aa 4”…
Is there a way to make it work ?
Thanks