SMLNJ - Typcon与声明类型

时间:2017-08-19 11:56:37

标签: types sml lex

我有以下问题:我正在使用ML中的A. Appel编译器,我编写了以下简单结构

signature Tiger_Tokens = 
sig
    type linenum;
    type token;
    val ADD : linenum*linenum -> token;
    val INT : string*linenum*linenum -> token;
    val EOF : linenum*linenum -> token;
end

structure Tokens :> Tiger_Tokens =
    struct
        type linenum = int;
        type token = string

        fun ADD(i,j) = "ADD"
        fun INT(number, i, j) = "INT"
        fun EOF(i,j) = "EOF"
    end

使用ML-lex库我用

编译它
type lexresult = Tokens.token
val lineNum = ref 1;
fun eof() = Tokens.EOF(!lineNum, !lineNum)

%%
digits=[0-9];
%%
\n => (!lineNum = (!lineNum) + 1; lex());
"+" => (Tokens.ADD(yypos,yypos+1));
{digits}+ => (Tokens.INT(yytext, yypos,yypos+1));

我收到以下错误

tiger.lex.sml:172.8-172.33 Error: operator and operand don't agree [tycon mismatch]
  operator domain: Tokens.linenum * Tokens.linenum
  operand:         int * int
  in expression:
    Tokens.ADD (yypos,yypos + 1)

现在显然我已将类型linenum设置为int。但是当我调用一个期望类型linenum(它是int)的函数,并且我传递一个int作为参数(yypos)时,它会要求Token.linenum不是int。因为我这样设置它不是一个int吗?或者SML将这些视为不同类型。如果他们确实将它们视为不同的类型,那么除了命名特殊的'之外,类型声明的重点是什么?有点int ??

提前致谢。

2 个答案:

答案 0 :(得分:2)

问题在于您拥有的签名归属,即:>部分:

structure Tokens :> Tiger_Tokens =

这样做有效地隐藏了Tokens中的所有类型。它被称为 opaque 签名归属。

还有另一种形式会实际暴露所有类型:透明签名归属:

structure Tokens : Tiger_Tokens =

中间地带被称为半透明签名归属,看起来像这样:

structure Tokens :> Tiger_Tokens where type linenum = int =

这只公开了linenum类型,而token仍然是抽象的。

答案 1 :(得分:0)

所以我实现的解决方案是在签名中声明类型。换句话说

signature Tiger_Tokens = 
sig
    type linenum = int;
    type token;
    val ADD : linenum*linenum -> token;
    val INT : string*linenum*linenum -> token;
    val EOF : linenum*linenum -> token;
end

但是你仍然需要一点点恢复,你仍然需要在你的结构中重新声明它。希望这有助于某人!