1

我目前正在学习 SML,我有一个关于我没有名字的问题。我们暂时称它为“类型别名”。假设我有以下数据类型定义:

datatype 'a stack = Stack of 'a list;

我现在想添加一个显式的“空堆栈”类型。我可以通过将它添加到数据类型来做到这一点:

datatype 'a stack = emptystack | Stack of 'a list;

现在我可以模式匹配像“push”这样的函数:

fun push (emptystack) (e:'a) = Stack([e])
  | push (Stack(list):'a stack) (e:'a) = Stack(e::list);

这里的问题是Stack([])并且emptystack是不同的,但我希望它们是相同的。所以每次 SML 遇到一个Stack([])它应该“知道”这是emptystack(在推送的情况下它应该使用空堆栈匹配)。

有没有办法做到这一点?

4

3 回答 3

2

这种混叠在 SML 中是不可能的。

相反,如果这是您想要的,您应该将您的数据类型设计为在其表示中明确。

您可能更适合类似于更多定义的'a list东西:

datatype 'a stack = EmptyStack | Stack of 'a * 'a stack;

这样做的缺点是不允许您在其上使用列表函数,但您确实得到了一个显式的空堆栈构造函数。

于 2012-05-04T11:43:21.090 回答
2

简短的回答是:不,这是不可能的。

您可以使用代码创建类型别名

type number = int

val foo : number -> int -> number =
 fn a => fn b => a+b

val x : int = foo 1 3;
val y : number = foo 1 3;

但是,顾名思义,它只适用于类型。您的问题适用于没有语法的值构造函数。

于 2012-05-04T11:47:47.263 回答
0

由于您想要一个值emptystack与另一个值同义Stack [],因此您可以将要查找的内容称为“值别名”。与内置运算符=或模式匹配进行比较的值不允许使用别名。

您可以通过创建自己的相等运算符来实现这一点,但您将失去使用内置的能力=(因为标准 ML 不支持自定义运算符重载)以及在您的类型的值构造函数上进行模式匹配的能力。

或者,您可以为您的类型构造一个范式并始终比较范式。只要实际可行,请遵循 Sebastian 的明确建议。在某些情况下,明确的代数类型将比允许以不同方式表示相同值的简单代数类型复杂得多。

于 2012-05-04T12:58:20.367 回答