5.3.1 F# 中的差别联合(discriminated unions)
在函数编程中,像这种突然出现的类型相当频繁,所以,函数语言倾向于使创建和使用类型更方便。在 F# 中,这种支持功能称为差别联合(discriminated unions)。与元组不同,差别联合必须事先声明,因此,在创建表示计划的值之前,必须声明这个类型,要有名字,最重要的是能够表示可选项。清单 5.3 显示了在 F# 中表示计划的类型。
清单 5.3 使用差别的计划类型 (F#)
type Schedule =
|Never
|Once of DateTime
|Repeatedly of DateTime * TimeSpan
创建 Schedule 类型时,我们组合了几种情况;为了能够区分不同选项,我们还为每个选项指定了名字(Never、Once 和 Repeatedly)。名字通常称为识别器(discriminators),因为,它们区分各种情况,即,Schedule类型的每个值携带其识别器,选定的选项保存在值中(例如,示例的最后一种情况中的 DateTime 和 TimeSpan)。可以发现,一个可选项保存了多个值时,我们使用了星号,这类似于创建元组的语法,因此,可以看到,两个概念(多值和可选值)很好地结合到一起了。
创建 Schedule 的类型值时,我们还需要识别器,因为,识别器描述了我们将使用哪种情况。清单 5.4 显示了几个示例。
清单 5.4 创建差别联合值(F# Interactive)
> open System;;
> let tomorrow =DateTime.Now.AddDays(1.0)
letnoon = new DateTime(2008, 8, 1, 12, 0, 0)
letdaySpan = new TimeSpan(24, 0, 0);;
val tomorrow : DateTime
val noon : DateTime
val daySpan : TimeSpan
> let schedule1 = Never;; <-- 无计划事件
val schedule1 : Schedule = Never
> let schedule2 = Once(tomorrow);; <-- 只发生一次的事件
val schedule2 : Schedule = Once(2.8.200817:29:07)
> let schedule3 = Repeatedly(noon,daySpan);; <-- 每天发生的事件
val schedule3 : Schedule =Repeatedly(1.8.2008 12:00:00, 1.00:00:00)
可以发现,创建 Schedule 类型值相当容易。使用识别器作为值构造函数,这类似于前面创建元组使用的值构造函数,比如,(7,"seven")。这里的语法看起来就像调用函数,对于没有任何额外参数值的选项,只写识别器名字;有多个参数值的选项,写出的参数值就好像是一个元组。
当然,如果不真正使用,光创建值是毫无意义的,下面,我们将尝试用计划来进行一些计算。