输入自己输入 - SML

时间:2014-06-09 14:56:20

标签: functional-programming sml smlnj

我是SML和这种编程风格的新手,我遇到了一些问题。我在ML中有一项任务,但我在建模数据方面遇到了一些问题。我在C中解决了同样的问题,但是我在SML / NJ中遇到了问题。这就是我想要的。

我在C中有一个结构,如下所示:

struct myStr {
    int someData;
    myOtherStruct someOtherData;
    struct myStr * next;
    struct myStr * prev;
}

基本问题是我根据struct myStr对指向struct myStr(或someOtherData,无关紧要)的指针数组进行了排序,然后我将一些值更新为下一个{ {1}}并将下一个struct myStr重新排序到数组中,以便对其进行排序,然后循环直到结束。

我在C上的复杂度相当高,因为排序需要O(nlogn)并重新排序:O(1)找到下一个myStr和O(logn)将这个特定元素重新排序到数组。

我在将此建模为SML时遇到了问题。

首先,我开始使用列表执行此操作,但每次都需要更改值。所以我开始考虑refs和数组(我知道它不是最好的东西)。

我在ML中考虑了以下内容:使用类型:

struct myStr

但这在ML中不起作用,因此产生以下错误:

type myStr = { 
    someData : int, 
    someOtherData : myOtherType,
    next : myStr ref, 
    prev :  myStr ref
}

基本问题是我想快速访问下一个元素(不是数组中的下一个元素)(比如在C中)。上述类型的想法在SML中不起作用。

我应该怎样做才能让上述类型工作,或者是否还有其他想法可以正确建模我的数据,以便得到我想要的东西?

谢谢。

1 个答案:

答案 0 :(得分:1)

显然,在SML中输入别名(使用type关键字定义的)不能递归。要定义递归类型,您需要使用datatype关键字定义代数数据类型。这样你的代码可以这样编译:

datatype myStr = MyStr of
  { 
    someData : int, 
    someOtherData : myOtherType,
    next : myStr ref, 
    prev :  myStr ref
  }

那说这个定义仍然很成问题。具体而言,它不允许有限(即非圆形列表)。此外,您将无法定义此类型的任何非递归值(但如果您只打算表示循环列表,那么值很自然需要递归)。

我假设您的C代码通过让最后一个节点的下一个指针(以及第一个节点的prev指针)为空来表示非循环列表。问题是ML中的ref不能为空,因此您不能在ML中使用相同的系统。因此,如果您需要非循环列表,则需要添加一个明确的Empty值,而不是null

datatype myStr = MyStr of
  { 
    someData : int, 
    someOtherData : myOtherType,
    next : myStr ref, 
    prev :  myStr ref
  }
  | Empty
PS:你说这是一项任务,但你并没有真正说出这项任务究竟要求你做什么。如果赋值是针对SML而且并没有特别要求你使用ref s / mutation,我会假设你应该在没有变异的情况下解决你的问题,所以你需要考虑一个不同的方法