如何在sml中定义新签名

时间:2016-03-30 10:47:35

标签: types sml smlnj type-declaration

我正在尝试将现有的int库扩展到名为" bigint"的新库。我将数据类型bigint的类型保留为int list。基本上,我想要一个函数(让我们称之为getbigint)接受任何int并将其每个数字存储在int list的单独单元格中,然后返回此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;*)

给出错误。

1 个答案:

答案 0 :(得分:1)

签名不执行任何操作。它描述了一个结构对外界的看法。将其视为规范。与之匹配的结构必须提供签名中元素的实现。请注意,运行代码时会出现以下错误:

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)。