I'm using phantom types to emulate the state of a stack, as a wrapper module for ocaml-lua (Lua communicates with C/OCaml through a stack). Small code example:
type 's t
type empty
type 's table
type top
val newstate : unit -> empty t (* stack empty *)
val getglobal : empty t -> top table t (* stack: -1 => table *)
Certain stack operations are possible on both tables and array-tables (no real arrays in Lua); some aren't. So if I have types
type 's table
type 's array
I want a kind like table-or-array for functions that operate on both types, but still being able to forbid e.g. rawgeti
(array operation) on tables. objlen
is a stack operation that returns the "length" of the element at the top of the stack. This element can be both table or array-table. At the moment, the wrapper function is defined as follows:
val objlen : (top table) t -> int
What I want is
val objlen : (top table-or-array) t -> int
That is, array
and table
is subtypes of table-or-array
.
Any ideas?
Regards Olle
Edit
After considerations, I came up with this:
module M : sig
type ('s, 't) t
(* New Lua state with empty stack *)
val newstate : unit -> (unit, unit) t
(* Get table *)
val getglobal : ('a) t -> ([< `table | `string | `number | `fn], 'a) t
(* Get array index and put "anything" on top of stack *)
val rawgeti : ([`table], 'a) t -> ([< `table | `string | `number | `fn], [`table] * 'a) t
(* String on top of stack *)
val tostring : ([`string], _) t -> string
(* Table or array-table on top of stack *)
val objlen : ([`table], _) t -> int
val pop : ('a, 'b * 'c) t -> ('b, 'c) t
end = struct
type top
type ('s, 't) t = string (* Should really be Lua_api.Lua.state *)
(* Dummy implementations *)
let newstate () = "state"
let gettable s = s
let getarray s = s
let rawgeti s = s
let tostring s = "Hello phantom world!"
let objlen s = 10
let pop s = s
end
The stack at type level should now know neither more nor less than the stack itself. E.g. rawgeti will push on stack any type.