For instance:
vagrant@precise32:/vagrant$ rlwrap sml
Standard ML of New Jersey v110.76 [built: Mon May 12 17:11:57 2014]
- TextIO.StreamIO.inputLine ;
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val it = fn : ?.TextIO.instream -> (string * ?.TextIO.instream) option
- val s = TextIO.openIn "README.md" ;
val s = - : TextIO.instream
- TextIO.StreamIO.inputLine s ;
stdIn:3.1-3.28 Error: operator and operand don't agree [tycon mismatch]
operator domain: ?.TextIO.instream
operand: TextIO.instream
in expression:
TextIO.StreamIO.inputLine s
-
I know that dummy type variables created due to the value restriction will have question marks in them, e.g.
- [] @ [];
stdIn:17.1-17.8 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val it = [] : ?.X1 list
... but this doesn't apply to the example above as the value restriction isn't involved.
In these lecture notes, I found the following comment, on page 23:
In fact, as indicated by the question marks ? in the error
message, it now has a type that cannot even be named anymore,
since the new but identically named definition of mylist shadows
it.
But this is referring to a type checking error, and anyway my example with TextIO.StreamIO this shouldn't apply as nothing is being shadowed.
edited to add
So I figured out my actual problem, which was how to get a ?.TextIO.instream
from a filename, but I still don't really know what the question marks are about:
vagrant@precise32:/vagrant$ rlwrap sml
Standard ML of New Jersey v110.76 [built: Mon May 12 17:11:57 2014]
val fromFile : string -> TextIO.StreamIO.instream =
= TextIO.getInstream o TextIO.openIn ;
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val fromFile = fn : string -> ?.TextIO.instream
- TextIO.getInstream ;
val it = fn : TextIO.instream -> ?.TextIO.instream
- TextIO.StreamIO.input1 (fromFile "README.md") ;
val it = SOME (#"#",-) : (TextIO.StreamIO.elem * ?.TextIO.instream) option
-
second edit
I discovered that Poly/ML doesn't use these question marks when printing types, so I assume this is something specific to SML/NJ:
Poly/ML 5.5.1 Release
> TextIO.StreamIO.inputLine ;
val it = fn:
TextIO.StreamIO.instream -> (string * TextIO.StreamIO.instream) option
> val fromFile : string -> TextIO.StreamIO.instream =
TextIO.getInstream o TextIO.openIn ;
# val fromFile = fn: string -> TextIO.StreamIO.instream
> TextIO.getInstream ;
val it = fn: TextIO.instream -> TextIO.StreamIO.instream
>
I'd still be curious if anyone knows under what circumstances SML/NJ prints these questions marks and what the story is behind them...
I believe this is specific to SML/NJ, and they are used when printing a type that does not have an accessible name (or probably, when the name that SML/NJ comes up with it is not accessible, since SML/NJ seems to just use some heuristic for printing types at the REPL). The value restriction is one way that such types arise (here SML/NJ chooses to unfiy the type with some useless new type). Here's another simple interaction that demonstrates another way, when the only name for a type (S.t) is shadowed by a new declaration of S:
- structure S = struct datatype t = X end;
structure S :
sig
datatype t = X
end
- val y = S.X;
val y = X : S.t
- structure S = struct end;
structure S : sig end
- y;
val it = X : ?.S.t
I think that in your example, there are multiple substructures called TextIO in the basis, and the toplevel TextIO structure is probably shadowing the one you're accessing. SML/NJ may also just be choosing a bad name for the type and not realizing that there's a sharing declaration or something that makes it possible to write the type down.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With