例如:
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
-
Run Code Online (Sandbox Code Playgroud)
我知道由于值限制而创建的虚拟类型变量将在其中包含问号,例如
- [] @ [];
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
Run Code Online (Sandbox Code Playgroud)
...但这不适用于上面的示例,因为不涉及值限制.
在这些讲义中,我发现了以下评论,第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.
Run Code Online (Sandbox Code Playgroud)
但这是指一个类型检查错误,无论如何我的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
-
Run Code Online (Sandbox Code Playgroud)
第二次编辑
我发现Poly/ML在打印类型时不使用这些问号,所以我认为这是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
>
Run Code Online (Sandbox Code Playgroud)
如果有人知道在什么情况下SML/NJ打印出这些问题标记以及它们背后的故事,我仍然很好奇......
小智 5
我相信这是 SML/NJ 特有的,并且在打印没有可访问名称的类型时使用它们(或者可能,当 SML/NJ 提供的名称不可访问时,因为 SML/NJ 似乎只需在 REPL 中使用一些启发式打印类型即可)。值限制是此类类型出现的一种方式(这里 SML/NJ 选择用一些无用的新类型来取消该类型)。这是另一个简单的交互,演示了另一种方式,当类型的唯一名称 (St) 被新的 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
Run Code Online (Sandbox Code Playgroud)
我认为在您的示例中,基础中有多个名为 TextIO 的子结构,并且顶层 TextIO 结构可能会隐藏您正在访问的结构。SML/NJ 也可能只是为类型选择了一个错误的名称,而没有意识到存在共享声明或使得可以写下类型的东西。