榆树中的标记工会

Tagged Unions in Elm

我正在阅读 http://elm-lang.org/guide/model-the-problem 并且想更好地理解 Elm 中的标记联合。具体来说,我遇到了这个例子:

type Scale = Normal | Logarithmic
type Widget
    = ScatterPlot (List (Int, Int))
    | LogData (List String)
    | TimePlot Scale (List (Time, Int))

我认为的解读方式如下:

  1. Scale 是一种具有 2 个可能值的类型:NormalLogarithmic
  2. Widget 是一种具有 3 个可能值的类型:ScatterPlotLogDataTimePlot

但是,如何解释 ScatterPlot 中的 (List (Int, Int)) 部分?同样,我如何解释 TimePlot 中的 Scale (List (Time, Int)) 部分?

只需将它们视为函数签名即可。所以必须像这样创建散点图

ScatterPlot [(1,1), (2,2)]

并且当您在 case 语句中进行模式匹配时

case widget of 
  ScatterPlot l -> l -- l is from type (List (Int, Int)) 
  LogData l -> l -- l is from type  (List String)
  TimePlot l -> l -- l is from type Scale (List (Time, Int))

List 是一个内置类型,接受一个参数(另一种类型),意思是 "a list containing values of this type as its elements"。所以 List (Int, Int)(Int, Int) 的列表。那么 (Int, Int) 是什么?

一般来说,任何 (a, b) 都是一个成员类型为 a 和类型 b 的元组。元组有点像没有字段名称的记录,因此您只能通过元素的位置来区分元素——但与列表不同的是,元素可以是不同类型的。所以 (Int, Int) 是一个包含两个 Int 的元组,其中 Int 只是一个整数。

因此,List (Int, Int) 是两个整数的元组列表。

使用 TimePlot 你实际上有两个不同的类型参数 - ScaleList (Time, Int)。鉴于 List (Int, Int) 的解释,后者现在应该有意义 - 只是元组将 Time 作为其第一种类型而不是 Int.

所以TimePlot将两个类型作为参数,就变成了TimePlot Scale (List (Time, Int)).

在 Elm 和相关语言中,类型符号(和函数应用程序)被定义为任何表达式 a b c d 表示 a,参数为 bcd。如果 c d 是一个参数,则将其放在括号中。

正如 Andreas 所说,将联合 'tags' 视为函数 - 它们确实是函数,事实上它们被称为 "type constructors"。 TimePlot 是一个接受 ScaleList (Time, Int) 并返回 Widget 的函数。 Normal是一个没有参数的函数,其中returns一个Scale,依此类推。