【问题标题】:Type with reference to itself - SML引用自身的类型 - SML
【发布时间】:2018-03-25 04:00:48
【问题描述】:

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

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

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

基本问题是我根据someOtherData对指向struct myStr(或struct myStr,没关系)的指针数组进行排序,然后我将一些值更新为下一个struct myStr并重新排序下一个struct myStr 到数组中,所以它被排序,然后我循环直到结束。

我在使用 C 时得到了相当不错的复杂性,因为排序需要 O(nlogn) 并且重新排序需要:O(1) 来找到下一个 myStr 和 O(logn) 来将这个特定元素重新排序到数组中。

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

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

我在 ML 中使用类型想到了以下内容:

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

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

stdIn:1.56-1.61 Error: unbound type constructor: myStr                                      
stdIn:1.38-1.43 Error: unbound type constructor: myStr  

基本问题是我想快速访问下一个元素(不是数组中的下一个元素)(就像在 C 中一样)。上面关于类型的想法在 SML 中不起作用。

我应该怎么做才能使上述类型正常工作,或者是否有任何其他想法可以正确地对我的数据进行建模以便得到我想要的?

谢谢。

【问题讨论】:

  • 您能解释一下您所说的“不起作用”是什么意思吗?您收到错误消息吗?如果有,是哪一个?
  • 在ml中的类型定义后添加了上面的错误。这是stdIn:1.56-1.61错误:未绑定类型构造函数:myStr stdIn:1.38-1.43错误:未绑定类型构造函数:myStr。但我坚信,即使有一种方法来定义这种类型,它也不是这种编程风格的最佳方法。

标签: functional-programming sml smlnj


【解决方案1】:

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

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

也就是说这个定义还是很有问题的。具体来说,它不允许有限(即非循环列表)。此外,您将无法定义此类型的任何非递归值(尽管如果您只打算表示循环列表,则这些值需要递归是很自然的)。

我假设您的此代码的 C 版本通过让最后一个节点的 next 指针(和第一个节点的 prev 指针)为空来表示非循环列表。问题在于 ML 中的 refs 不能为空,因此您不能在 ML 中使用相同的系统。因此,如果您需要非循环列表,则需要添加一个显式的 Empty 值,以代替 null

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

PS:你说这是一项任务,但你并没有真正说出任务要求你做什么。如果作业是针对 SML 的,并且没有明确要求您使用 refs/mutation,我认为您应该在没有突变的情况下解决您的问题,因此您需要考虑一种不同的方法。

【讨论】:

  • 抱歉忘了说。我的 C 代码实际上是一个循环列表。那么任务是这样的。给定一条具有离散位置和有限跑步者的圆形道路,我从一个文件中读取每个跑步者的位置和速度(两个跑步者不能具有相同的起始位置)。所有跑垒员向同一方向(左或右)跑,如果跑垒员从他身上抓住跑垒员,他前面的跑垒员将被取消资格。我们被要求按照被取消资格的顺序打印被取消资格的跑步者。
  • Nit:不是添加Empty,而是添加nextprev 选项引用可能是更好的解决方案。
  • 我也会试试的,谢谢你的信息。顺便说一句,我如何访问例如存储变量 c1 的“someData”:例如 myStr?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多