【问题标题】:Type inference in SMLSML 中的类型推断
【发布时间】:2012-05-04 11:26:30
【问题描述】:

我目前正在学习 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(在推送的情况下,它应该使用空堆栈匹配)。

有没有办法做到这一点?

【问题讨论】:

  • 只是为了记录,它被称为inference,而不是interference。 SML 编译器推断表达式的类型。它不会干扰 :)
  • 这引出了一个问题:为什么你甚至想这样做? stack 的第二个版本比第一个更好吗?通常,人们希望删除多余的案例而不是引入它们。

标签: sml


【解决方案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】:

    这样的别名在 SML 中是不可能的。

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      您可以通过创建自己的相等运算符来实现此目的,但您将无法使用内置的 =(因为标准 ML 不支持自定义运算符重载)以及在您的类型的值构造函数。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-30
        • 2015-11-11
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 2011-06-20
        相关资源
        最近更新 更多