我在榆树的联合类型中缠绕着一些麻烦.我理解简单的用例就像
type Visibility = All | Active | Completed
Run Code Online (Sandbox Code Playgroud)
这意味着Visiblity的值可以是All,Active或Completed.到现在为止还挺好.然而,我感到困惑的地方
type Msg
= OnFetchMails (WebData (List Mail))
| OnFetchSmss (WebData (List SMS))
Run Code Online (Sandbox Code Playgroud)
我该怎么解释这个?这是否意味着Msg可以是类型函数OnFetchMails,它采用类型函数WebData来获取邮件列表?或者我该如何解释?我认为那(WebData (List Mail))
不是有效载荷吗?
有趣的是,我可以在不了解它的情况下让它工作
Ale*_*Lew 11
定义联合类型时,列出构造该类型值的所有方法.在最简单的形式中,该定义如下所示:
type Visibility
= All
| Active
| Completed
Run Code Online (Sandbox Code Playgroud)
正如你所推测的那样,这会声明类型Visibility
并定义三个值,所有类型都是如此Visibility
.构造类型值的唯一方法Visibility
是使用这三个选项之一.因此,我们经常称它们为"构造函数".
这是一个稍微复杂的联合类型定义:
type TrainStatus
= OnTime
| Delayed Int
Run Code Online (Sandbox Code Playgroud)
正如您所料,这定义了两个新的"构造函数" OnTime
和Delayed
.但看看他们的类型:
OnTime : TrainStatus
Delayed : Int -> TrainStatus
Run Code Online (Sandbox Code Playgroud)
该OnTime
构造函数采用零个参数,所以是一个简单的值; 它已经是一个TrainStatus
.但是,Delayed
声明为一个参数的构造函数:它是一个函数创建一个新TrainStatus
的出来Int
.因此,Delayed 5
,Delayed 10
,和Delayed 100
都是有效的TrainStatus
值.(我们可以将它们解释为"延迟5分钟"或类似的东西.)
构造函数可以使用多个参数; 例如,如果我们想要作为String包含延迟的原因:
type TrainStatus
= OnTime
| Delayed Int String
ts : TrainStatus
ts = Delayed 20 "The conductor took a short nap."
Run Code Online (Sandbox Code Playgroud)
它定义了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
Run Code Online (Sandbox Code Playgroud)
实际上,是的,您可以将其视为与每个分支一起的有效载荷.
type Msg
= OnFetchMails (WebData (List Mail))
| OnFetchSmss (WebData (List SMS))
Run Code Online (Sandbox Code Playgroud)
意味着类型的值Msg
可以是,或者OnFetchMails
具有某种类型的值WebData (List Mail)
; 或者它可以是OnFetchSmss
与WebData (List SMS)
伴随它.
它们有时被称为标记联合,因为它们的行为很像C样式的union
构造,其中包含一个标记值,该标记值表示union中的哪个选项是当前有效的(并且实际上有许多具有此类结构的语言)以这种方式实现它们).
它们还可以被建模为抽象基Msg
类型的一系列子类,为每个子类中的有效负载添加存储,并要求将有效负载作为构造函数参数提供.