标准ML类型中的问号是什么意思?

时间:2014-05-12 22:13:45

标签: 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 -> (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

...但这不适用于上面的示例,因为不涉及值限制。

these讲义中,我发现了以下评论,第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
- 

第二次修改

我发现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
> 

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

1 个答案:

答案 0 :(得分:3)

我相信这是特定于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也可能只是为该类型选择了一个坏名称而没有意识到存在共享声明或者可以将该类型写下来的东西。