标准 ML 教程代码未使用 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 没有函数类型。