Understanding type variables in type annotations

rob*_*obC 3 types type-variables parametric-polymorphism elm

The Elm docs illustrate type variables like this:

> List.reverse
<function> : List a -> List a
Run Code Online (Sandbox Code Playgroud)

...the type variable a can vary depending on how List.reverse is used. But in this case, we have an a in the argument and in the result. This means that if you give a List Int you must get a List Int as well.

The docs for Maybe.map show this annotation:

map : (a -> b) -> Maybe a -> Maybe b
Run Code Online (Sandbox Code Playgroud)

那么为什么这些类型被注释为a以及b何时它们必须是相同的类型?
我希望a跟踪类型,即:

map : (a -> a) -> Maybe a -> Maybe a
Run Code Online (Sandbox Code Playgroud)

gle*_*nsl 5

那么为什么这些类型被注释为a以及b何时它们必须是相同的类型?

他们没有!如果map确实对输入参数类型和返回类型使用相同的类型变量,它们会使用相同的类型变量,但map可以从一种类型转换为另一种类型。这是一个具体的例子:

Maybe.map String.fromInt (Just 42)
Run Code Online (Sandbox Code Playgroud)

String.fromInt具有类型Int -> String,我们将其用作Maybe.map. 因此,如果我们尝试将其替换为 of map

String.fromInt : (Int -> String)
Maybe.map      : (a   -> b     ) -> Maybe a -> Maybe b
Run Code Online (Sandbox Code Playgroud)

我们看到Int替代品aString替代品b。因此Maybe a必须是Maybe Int并且Maybe b必须是Maybe String。这意味着如果我们尝试给它一个Maybe String

Maybe.map String.fromInt (Just "foo")
Run Code Online (Sandbox Code Playgroud)

我们会得到一个错误:

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
Run Code Online (Sandbox Code Playgroud)