Hi,
I found myself defining a type that would both contain a module type and a type constraint:
module type Screen = sig
type state
type message
val init : state
[...]
val emit : state -> message option
end
type 'a screen = (module Screen with type message = 'a) constraint 'a = [> `quit]
That is supposed to express that screens emit messages, and that one of the messages can be "quit". Now I've got some trouble when using the 'a screen type in a function that unpack the module it contains:
let f (screen : 'a screen) =
let module Screen = (val screen : Screen) in
match Screen.(emit init) with
| Some `quit -> 1
| _ -> 0
;;
Error: This expression has type
([> `quit ] as 'a) screen = (module Screen with type message = 'a)
but an expression was expected of type (module Screen)
New attempt:
# let f (screen : 'a screen) =
let module Screen = (val screen : Screen with type message = 'a) in
match Screen.(emit init) with
| Some `quit -> 1
| _ -> 0
;;
Error: Unbound type parameter 'a
Though here I'm not sure the error is right. New attempt:
# let f (type s) (screen : s screen) =
let module Screen = (val screen : Screen with type message = s) in
match Screen.(emit init) with
| Some `quit -> 1
| _ -> 0
;;
Error: This type s should be an instance of type [> `quit ]
Which makes sense. So here is my question: is there a way to impose a constraint on the "newtype" introduced in argument? Let me say that I'm aware I should write this more simply. For instance in the module type Screen, emit could have type state -> [`quit | `message of message]. So my question is only a matter of curiosity. Still, I'd be happy to know :o).
Cheers,
Philippe.