Elm类型变量

示例

类型变量是类型签名中没有大写字母的名称。与它们的大写字母(例如Int和)不同String,它们不代表单个类型,而是代表任何类型。它们用于编写可在任何一种或多种类型上运行的通用函数,对于在诸如List或的容器上进行写操作特别有用Dict。该List.reverse函数例如具有以下签名:

reverse : List a -> List a

这意味着它可以在列表上工作的任何类型的值,因此List Int,List (List String),这两个和任何其他的可以reversed全部相同。因此,a是可以代表任何类型的类型变量。

该reverse函数可以在其类型签名中使用任何未大写的变量名,除了少数特殊类型变量名,例如number(有关更多信息,请参见相应的示例):

reverse : List lol -> List lol

reverse : List wakaFlaka -> List wakaFlaka

类型变量的名称只有在单个签名中存在不同类型变量的情况下才有意义,例如map列表中的函数:

map : (a -> b) -> List a -> List b

map将某个函数从任何类型转换a为任何类型b,以及一个包含某种类型元素的列表a,并返回某种类型元素的列表b,它通过将给定函数应用于列表中的每个元素而获得。

让我们将签名具体化,以更好地了解这一点:

plusOne : Int -> Int
plusOne x = 
    x + 1

>List.mapplusOne
<function> : List Int -> List Int

正如我们所看到的,a = Int而b = Int在这种情况下。但是,如果map具有类似的类型签名map : (a -> a) -> List a -> List a,则它适用于对单个类型进行操作的函数,并且您将永远无法使用该map函数来更改列表的类型。但是,由于类型签名map有多个不同类型的变量,a并且b,我们可以用map更改列表的类型:

isOdd : Int -> Bool
isOdd x =
    x % 2 /= 0

>List.mapisOdd
<function> : List Int -> List Bool

在这种情况下,a = Int和b = Bool。因此,为了能够使用可以接受和返回不同类型的函数,必须使用不同的类型变量。