如何在 sml 中定义新签名

How to define new signature in sml

我正在尝试将现有的 int 库扩展到一个名为 "bigint" 的新库。我将数据类型 bigint 的类型保留为 int 列表。基本上,我想要一个函数(我们称之为 getbigint),它接受任何 int 并将其每个数字存储在一个单独的 int 列表单元格中,然后 return 这个 int 列表。所以如果我输入:

getbigint 9

它应该给我:

val it =[9]:bigint 

我怎样才能做到这一点?目前,我假设此函数的输入仅为单个数字 int。这是我到目前为止所做的:

signature BigInt =
    sig
        type bigint = int list
        val getbigint: int -> bigint
    end;

structure struct_bigint : BigInt = 
    struct
        fun getbigint (i:int) = 
            let
              val h = [i]:bigint
            in h
            end
    end
(*val j = getbigint 9;*)

出现错误。

签名不执行任何操作。它描述了一个结构在外界看来是什么样的。将其视为规范。匹配它的结构必须提供签名中元素的实现。请注意,当您 运行 您的代码时,您会收到以下错误:

Error: unmatched type specification: bigint

SML 检测到您的签名中有与结构中相应实现不匹配的内容。

最小的修复方法是添加行

type bigint = int list

在结构定义前执行fun getbigint。这将允许行

val j = struct_bigint.getbigint 9;

上班。但是——

这行看起来有点傻
type bigint = int list

两次——一次在签名中,一次在结构中。而且,在某些方面,它 愚蠢的。

实现细节并不真正属于签名。在 签名 中使用 type bigint 并在 结构 中使用 int list 实现更有意义.这将允许您以后改变对实现的想法(比如您想要使用数组而不是列表),这样使用该结构的代码完全不受影响。类似于:

signature BIGINT =
    sig
        type bigint
        val getbigint: int -> bigint
    end

structure BigInt : BIGINT = 
    struct
        type bigint = int list

        fun getbigint (i:int): bigint = [i];            
    end;

我清理了你对 getbigint 的实现,因为其中的 let 绑定似乎有点毫无意义,并为签名(全部大写)和结构(驼峰)的名称选择了更惯用的名称首字母大写的案例。

最后,请注意 getbigint 9 无法开箱即用。您可以执行以下三项操作之一:

1) 显式使用限定名称:BigInt.getbigint 9

2) 使用行 val getbigint = BigInt.getbigint 赋予名称 getbigint 在当前范围内的预期含义

3) 使用行 open BigInt 将结构的定义移动到顶层,之后 getbigint 9 将按预期工作。

当我开始使用 SML 编程时,我常常打开很多结构(Char、`List 等)。如果你不加考虑地这样做,迟早你会 运行 进入错误,打开结构会引入名称冲突。出于这个原因,我现在几乎总是使用方法 1) 或 2)。