Ziqi Fan
Ziqi Fan

Reputation: 162

Standard ML tutorial code not compiled correctly with SML/NJ

I compiled the following code using the command: ./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"

and I got this error report:

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

It is the following code block that caused the failure:

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

Then I modified the block causing the issue slightly into a binding statement as follows:

(* 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"

To emphasize, the only difference is that the "let" block causing the issue was modified into the following binding statement:

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

and the code was compiled and run successfully with the following result:

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

It seems that the compiler did not like a "let" expression without being bound to a variable in this case. But compiling the "let" express alone was successful. What is the reason for the failure?

Upvotes: 0

Views: 65

Answers (1)

kopecs
kopecs

Reputation: 1732

The main issue is that you've (attempted to) put an expression at top level. You can only put declarations at the top level (excepting the REPL-used derived form where e is treated as val it = e).

Correspondingly

val n : real = 2.17


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

is parsed as one declaration. As you have two sequential expressions this would be an application expression, to wit, the application of 2.17 to the let expression. As the type error indicates, this is not permitted as 2.17 does not have a function type.

Upvotes: 1

Related Questions