Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What do questions marks mean in Standard ML types?

Tags:

sml

smlnj

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...

like image 402
michiakig Avatar asked May 12 '14 22:05

michiakig


1 Answers

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.

like image 72
Tom 7 Avatar answered Oct 06 '22 06:10

Tom 7