我目前正在学习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
(如果是push,则应该使用emptystack匹配)。
有没有办法实现这个目标?
答案 0 :(得分:1)
在SML中无法进行这种混叠。
相反,您应该将数据类型设计为在其表示中明确无误,如果这是您想要的。
您可能更适合使用类似于'a list
更多内容的内容:
datatype 'a stack = EmptyStack | Stack of 'a * 'a stack;
这有一个缺点,就是不要让你使用它上面的列表函数,但你得到一个显式的空堆栈构造函数。
答案 1 :(得分: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;
然而,顾名思义,它只适用于类型。你的问题是值构造函数,它没有语法。
答案 2 :(得分:0)
由于你想要的是一个值emptystack
与另一个值Stack []
同义,你可以调用你正在寻找的“值别名”。与内置运算符=
或模式匹配进行比较的值将不允许使用别名。
你可以通过创建自己的相等运算符来实现这一点,但是你将失去使用内置=
的能力(因为标准ML不支持自定义运算符重载)以及模式匹配的能力在你的类型的值构造函数。
或者,您可以为您的类型构建一个普通表单,并始终比较普通表单。只要实际可行,请遵循塞巴斯蒂安的建议,不要含糊不清。可能存在一种情况,其中明确的代数类型将比允许以不同方式表示相同值的更简单代数类型复杂得多。