标准 ML 教程代码未使用 SML/NJ 正确编译

Standard ML tutorial code not compiled correctly with SML/NJ

我使用命令编译了以下代码: ./sml /media/ziqi/storage/sml_code/test.sml :

(* Variables and Declarations *)

type float = real
type count = int and average = real 

type float = real and average = float

val m : int = 3+2 
val pi : real = 3.14 and e : real = 2.17

val x : float = Math.sin pi

val m : int = 3+2 
val n : int = m*m 

val n : real = 2.17


let
    val m : int = 3
    val n : int = m*m
in
    m*n
end

val m : int = 2
val r : int =
    let
    val m : int=3
    val n : int=m*m
    in
    m*n
    end * m

val m : int = 0 
val x : real = Math.sqrt 2.0 
val c : char = #"a"

我收到了这个错误报告:

Standard ML of New Jersey (64-bit) v110.99 [built: Tue Mar 23 10:47:59 2021]
[opening /media/ziqi/storage/sml_code/test.sml]
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[library $SMLNJ-BASIS/(basis.cm):basis-common.cm is stable]
[autoloading done]
/media/ziqi/storage/sml_code/test.sml:16.5-24.4 Error: operator is not a function [tycon mismatch]
  operator: real
  in expression:
    2.17 let val m : int = 3
    val n : int = m * m in m * n end

导致失败的是以下代码块:

let
    val m : int = 3
    val n : int = m*m
in
    m*n
end

然后我将导致问题的块稍微修改为如下绑定语句:

(* Variables and Declarations *)

type float = real
type count = int and average = real 

type float = real and average = float

val m : int = 3+2 
val pi : real = 3.14 and e : real = 2.17

val x : float = Math.sin pi

val m : int = 3+2 
val n : int = m*m 

val n : real = 2.17

val h : int = 
    let
        val m : int = 3
        val n : int = m*m
    in
        m*n
    end

val m : int = 2
val r : int =
    let
    val m : int=3
    val n : int=m*m
    in
    m*n
    end * m

val m : int = 0 
val x : real = Math.sqrt 2.0 
val c : char = #"a"

强调一下,唯一的区别是导致问题的“let”块被修改为以下绑定语句:

val h : int = 
    let
        val m : int = 3
        val n : int = m*m
    in
        m*n
    end

并且代码已编译并 运行 成功,结果如下:

Standard ML of New Jersey (64-bit) v110.99 [built: Tue Mar 23 10:47:59 2021]
[opening /media/ziqi/storage/sml_code/test.sml]
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[library $SMLNJ-BASIS/(basis.cm):basis-common.cm is stable]
[autoloading done]
type float = real
type count = int
type average = float
type float = real
type average = float
val m = <hidden> : int
val pi = 3.14 : real
val e = 2.17 : real
val x = <hidden> : float
val m = <hidden> : int
val n = <hidden> : int
val n = 2.17 : real
val h = 27 : int
val m = <hidden> : int
val r = 54 : int
val m = 0 : int
val x = 1.41421356237 : real
val c = #"a" : char

在这种情况下,编译器似乎不喜欢没有绑定到变量的“let”表达式。但是单独编译“让”表达是成功的。失败的原因是什么?

主要问题是您(试图)将表达式置于顶层。您只能将声明放在顶层(REPL 使用的派生形式除外,其中 e 被视为 val it = e)。

对应

val n : real = 2.17


let
    val m : int = 3
    val n : int = m*m
in
    m*n
end

被解析为一个声明。由于您有两个顺序表达式,因此这将是一个应用程序表达式,即 2.17 对 let 表达式的应用程序。如类型错误所示,这是不允许的,因为 2.17 没有函数类型。