我在榆树的联合类型中遇到了一些麻烦。我理解像
这样简单的用例type Visibility = All | Active | Completed
这意味着Visiblity的值可以是All,Active或Completed。到现在为止还挺好。我感到困惑的地方是
type Msg
= OnFetchMails (WebData (List Mail))
| OnFetchSmss (WebData (List SMS))
我该如何解读?这是否意味着Msg可以是类型函数OnFetchMails,它采用一个带有邮件列表的类型函数WebData?或者我该如何解释?
我不认为(WebData (List Mail))
是有效载荷吗?
有趣的是,我可以在不理解它的情况下让它工作
答案 0 :(得分:11)
定义联合类型时,列出构造该类型值的所有方法。在最简单的形式中,该定义如下所示:
type Visibility
= All
| Active
| Completed
正如您所推测的那样,这会声明类型Visibility
并定义三个值,所有类型都为Visibility
。构造Visibility
类型值的唯一方法是使用这三个选项之一。因此,我们经常称他们为#34;施工人员。"
这是一个稍微复杂的联合类型定义:
type TrainStatus
= OnTime
| Delayed Int
正如您所料,这定义了两个新的"构造函数," OnTime
和Delayed
。但看看他们的类型:
OnTime : TrainStatus
Delayed : Int -> TrainStatus
OnTime
构造函数接受零参数,因此只是一个值;它已经是TrainStatus
了。但是Delayed
被声明为单参数构造函数:它是一个函数,可以从TrainStatus
中创建一个新的Int
。因此,Delayed 5
,Delayed 10
和Delayed 100
都是有效的TrainStatus
值。 (我们可以将它们解释为"延迟5分钟"或类似的东西。)
构造函数可以接受多个参数;例如,如果我们想要作为字符串包含延迟的原因:
type TrainStatus
= OnTime
| Delayed Int String
ts : TrainStatus
ts = Delayed 20 "The conductor took a short nap."
定义Delayed : Int -> String -> TrainStatus
。
如果您获得TrainStatus
,则可以使用模式匹配提取其中的Int
和String
:
case ts of
OnTime ->
"Your train is on time!"
Delayed minutes reason ->
"Your train has been delayed by " ++ toString minutes ++ " because " ++ reason
答案 1 :(得分:7)
实际上,是的,您可以将其视为与每个分支一起的有效载荷。
type Msg
= OnFetchMails (WebData (List Mail))
| OnFetchSmss (WebData (List SMS))
表示Msg
类型的值可以是OnFetchMails
,其值为WebData (List Mail)
的值为OnFetchSmss
;或者可以WebData (List SMS)
附加union
。
他们有时称为标记的联盟,因为它们的行为很像C样式的Msg
构造,其中包含标记值说联盟中哪个选项是当前有效的选项(事实上,许多具有这种结构的语言都是这样实现的。)
它们也可以被建模为抽象基类{{1}}类型的一系列子类,为每个子类中的有效负载添加存储,并要求将有效负载作为构造函数参数提供。