As I understand it, in SML modules, to prevent every type from being hidden by opaque signature ascription, you can specify concrete types in the signature.
I'm trying to do that with a functor for making symbol tables, hiding the table type but leaving the entry type transparent. But whenever I do opaque ascription I can't access the entry type. Here are my signatures and functor:
signature ST_ENTRY = sig
type entry
val name : entry -> string
end
signature SYMTABLE = sig
structure E: ST_ENTRY
type symentry = E.entry
type symtable
val empty: symtable
val insert: symtable -> E.entry -> symtable
val lookup: symtable -> string -> E.entry option
end
functor SymtableFn (Ent:ST_ENTRY) :> SYMTABLE = struct
structure E = Ent
type symentry = E.entry
type symtable = E.entry list
val empty: symtable = []
fun fromList symlist = symlist
fun insert (tab: symtable) e = e::tab
end
Then, when I create an entry struct and instantiate the functor with it, like this:
structure Myentry : ST_ENTRY = struct
type entry = {name: string, typ: string}
fun name (e:entry) = #name e
end
structure Mytable = SymtableFn (Myentry)
val tab = Mytable.insert (Mytable.empty) {name="x", typ="str"}
I get a type clash for the last line, but if I turn off opaque ascription, it works fine. I tried with both SML/NJ and Moscow ML and get the same error. Why isn't this working like I think it should? Is there any way to make the entry type transparent?
You also need to specify that the resulting type E.entry
relates to the functor parameter. Just change the declaration of the functor to
functor SymtableFn (Ent:ST_ENTRY) :> (SYMTABLE where type E.t = Ent.entry) = struct ...
In fact, I'd drop substructure E
from signature SYMTABLE
and change the above to
functor SymtableFn (Ent:ST_ENTRY) :> (SYMTABLE where type symentry = Ent.entry) = struct ...