【问题标题】:Understanding type variables in type annotations理解类型注解中的类型变量
【发布时间】:2019-12-05 09:46:36
【问题描述】:
Elm docs 像这样说明类型变量:
> List.reverse
<function> : List a -> List a
...类型变量 a 可以根据 List.reverse 的使用方式而有所不同。但是在这种情况下,我们在参数和结果中都有一个 a。这意味着,如果您提供一个 List Int,您也必须得到一个 List Int。
Maybe.map 的文档显示此注释:
map : (a -> b) -> Maybe a -> Maybe b
那么,当它们必须是相同的类型时,为什么将类型注释为a 和b?
我希望a 跟踪类型,即:
map : (a -> a) -> Maybe a -> Maybe a
【问题讨论】:
标签:
types
elm
parametric-polymorphism
type-variables
【解决方案1】:
那么,当它们必须是相同的类型时,为什么将类型注释为a 和b?
他们没有!如果map 确实为输入参数类型和返回类型使用了相同的类型变量,那么map 可以从一种类型转换为另一种类型。这是一个具体的例子:
Maybe.map String.fromInt (Just 42)
String.fromInt 的类型为Int -> String,我们将其用作Maybe.map 的第一个参数。因此,如果我们尝试将其替换为 map:
String.fromInt : (Int -> String)
Maybe.map : (a -> b ) -> Maybe a -> Maybe b
我们看到Int 替换了a 和String 替换了b。因此Maybe a 必须是Maybe Int 而Maybe b 必须是Maybe String。这意味着如果我们尝试给它一个Maybe String:
Maybe.map String.fromInt (Just "foo")
我们会得到一个错误:
The 2nd argument to `map` is not what I expect:
1 | foo = Maybe.map String.fromInt (Just "foo")
^^^^^^^^^^
This `Just` call produces:
Maybe String
But `map` needs the 2nd argument to be:
Maybe Int