Sml 在标准ML类型中,问号是什么意思?

Sml 在标准ML类型中,问号是什么意思?,sml,smlnj,Sml,Smlnj,例如: 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 -&

例如:

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
- 
我知道由于值限制而创建的虚拟类型变量中会有问号,例如

- [] @ [];
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
。。。但这不适用于上面的示例,因为不涉及值限制

在课堂讲稿中,我在第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.
但这是指一个类型检查错误,无论如何,我的示例TextIO.StreamIO这不应该适用,因为没有任何内容被隐藏

编辑以添加

所以我解决了我的实际问题,那就是如何从文件名中获取
?.TextIO.instream
,但我仍然不知道问号是关于什么的:

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
- 
第二次编辑

我发现打印类型时不使用这些问号,所以我假设这是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
> 

我仍然很好奇,是否有人知道SML/NJ在什么情况下打印这些问号,以及它们背后的故事…

我相信这是SML/NJ特有的,并且在打印没有可访问名称的类型时使用它们(或者,当SML/NJ提供的名称不可访问时,因为SML/NJ似乎只是在REPL处使用一些启发式方法来打印类型)。值限制是此类类型出现的一种方式(这里SML/NJ选择使用一些无用的新类型来取消该类型的匹配)。下面是另一个简单的交互,它演示了另一种方式,当类型(s.t)的唯一名称被新的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
我认为在您的示例中,有多个子结构称为TextIO,并且顶级TextIO结构可能隐藏了您正在访问的结构。SML/NJ也可能只是为类型选择了一个不好的名称,而没有意识到存在共享声明或使写下类型成为可能的东西