【问题标题】:How to implement some sort of "nullable" types in Standard ML?如何在标准 ML 中实现某种“可空”类型?
【发布时间】:2013-08-06 20:47:39
【问题描述】:

说在标准 ML 中定义了几种数据类型:

datatype color = orange | navy | teal | silver | hsl of real * real * real;

datatype direction = east | north | west | south;

然后我定义一个使用上述数据类型的值:

type Cursor = int * int * color * direction;

val cursor : Cursor = (0, 0, orange, east);

它是一个“光标”,具有位置、绘图颜色和方向。 我希望它的属性最初是未定义的。我可以为每个 colordirection 数据类型添加一个构造函数(我将如何使用 int 位置值来做到这一点?),如下所示:

datatype color = orange | teal | silver | hsl of real * real * real | undefined;

datatype direction = east | north | west | south | undefined;

val cursor : Cursor = (0, 0, undefined, undefined);

我想这样做无需为每个数据类型显式定义一个额外的undefined 构造函数。你能想出一个好的、干净的解决方案吗?某种形式的泛型,无论类型如何,我都可以简单地使用“未定义值”的形式。粗略地说,类似于 Javas Nullable

我的动机是我的光标的属性最初是未定义的。

【问题讨论】:

    标签: sml smlnj


    【解决方案1】:

    为此,人们通常使用option 类型。

    您生成的机器人类型将是:

    type Robot = (int * int * color * direction) option;
    

    或组件方面。这也与自己简单地使用两个构造函数(一个表示未定义值,一个表示初始化值)创建数据类型相同,但option 是一种标准方法,它也鼓励单子编程风格。

    这可以确保您的类型安全,因为每当您破坏类型的值时,您都需要匹配两个构造函数。

    【讨论】:

    • 当然,我怎么会错过这个(已经在option上阅读了)!谢谢,我会尝试将其合并并返回并将您的答案标记为正确的答案:-)
    【解决方案2】:

    没有语法糖可以引用具有相同名称的不同构造函数。 (换句话说:标准 ML 不允许自定义重载。)相反,首先声明的构造函数被另一种类型的类似拼写构造函数覆盖。

    Haskell 有一个名为undefined 的值,在评估时会引发异常。因此该值的类型不受任何特定类型的限制,并且是多态的,这意味着 undefined 可以在任何地方使用。

    标准 ML 不能将此值定义为引发异常的别名,因为它是经过严格评估的。这意味着在声明val undefined = raise Undefined 的那一刻,就会抛出异常。但可以在尚未编写的程序部分使用raise Undefined,只要不立即对其进行评估。

    代数类型的一个非常重要的优势是,除非您明确地形成支持它的类型(例如使用'a option),否则您不会意外地拥有类似空的值。

    【讨论】:

    • +1 用于与 undefined 的比较,并注意到 Haskell 中的归约顺序(与 ML 中的严格相比)会导致差异。
    猜你喜欢
    • 1970-01-01
    • 2019-12-18
    • 2011-01-31
    • 2018-08-16
    • 1970-01-01
    • 2015-09-21
    • 1970-01-01
    • 2015-05-01
    • 2011-04-07
    相关资源
    最近更新 更多