2012-05-04 117 views
0

我目前在学习SML,并且对于我没有名字的东西有疑问。现在让我们称之为“输入别名”。假设我有以下数据类型定义:SML中的类型推断

datatype 'a stack = Stack of 'a list; 

我现在想添加一个明确的“空栈”类型。我可以这样将它添加到数据类型:

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

现在我可以匹配模式像“推送”功能:

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

这里的问题是,Stack([])emptystack是不同的,但我想他们是一样的。因此,每当SML遇到Stack([])时,它应该“知道”这是emptystack(在推送的情况下它应该使用空堆匹配)。

有没有办法做到这一点?

+1

只是为了记录,它被称为*推理*,而不是*干扰*。 SML编译器*推断*表达式的类型。它不*干扰* :) – jalf

+2

这引发了一个问题:*为什么*你甚至想要这样做?第二版“栈”比第一版更受欢迎?通常,人们想要删除多余的案例,而不是引入它们。 –

回答

1

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

您可以创建类型别名的代码

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; 

然而,正如它的名字说,它仅适用于类型。你的问题是价值构造函数,没有语法。

1

这种混叠在SML中是不可能的。相反,你应该设计你的数据类型在它们的表示中是明确的,如果这是你想要的。

你可能更适合的东西,酷似'a list更多的定义:

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

这有没有让你使用它的列表功能的缺点,但你得到一个明确的空堆栈构造函数。

0

既然你想要的是一个值emptystack是另一个值Stack []的代名词,你可以打电话给你正在寻找“价值别名”。与内置运算符=或模式匹配进行比较的值将不允许使用别名。

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

或者,您可以为您的类型构造一个正常形式,并且始终比较正常形式。只要切实可行,请按照塞巴斯蒂安的建议,即不含糊。在这种情况下,明确的代数类型比简单的代数类型复杂得多,它允许以不同的方式表示相同的值。