我是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中不起作用。
我应该怎样做才能让上述类型工作,或者是否还有其他想法可以正确建模我的数据,以便得到我想要的东西?
谢谢。
答案 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,我会假设你应该在没有变异的情况下解决你的问题,所以你需要考虑一个不同的方法