2012-10-29 30 views
1

说在标准毫升定义多个数据类型:如何在标准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); 

这是一个“光标”,有一个位置,绘制颜色,和一个方向。 我想要的是它的属性最初是undefined。我可以一个构造函数添加到每个colordirection数据类型(我会怎么做,与int位置值?),如下所示:具有明确定义的附加undefined

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); 

我想这样做没有每种数据类型的构造函数。你能想到一个好的,干净的解决方案吗?不管类型如何,我都可以简单地使用“未定义值”形式的某种形式的泛型。一个类似于Javas Nullable,把它粗糙。

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

回答

3

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

你所得机器人类型将是:

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

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

这让你输入安全,因为无论何时你毁坏这个类型的值,你都需要匹配两个构造函数。

+0

当然,我怎么会错过这个(已经阅读'选项')!谢谢,我会试着将这个结合起来,并将你的答案标记为正确答案:-) – amn

3

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

Haskell的值为undefined,当评估时,会引发异常。因此,该值的类型不受任何特定类型的约束,并且是多态的,这意味着未定义可以在任何地方使用。

标准ML不能将此值定义为抛出异常的别名,因为它是严格评估的。这意味着val undefined = raise Undefined被宣布的那一刻,抛出异常。但是可以在尚未编写的程序的某些部分使用raise Undefined,只要它不被直接评估。

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

+0

+1与'undefined'进行比较,并注意到Haskell中的缩减顺序(与ML中的strict相比)导致了区别。 –