首页 > 解决方案 > 将泛型类型变量统一到另一个现有类型

问题描述

下面是Elm 指南中的一句话

Task.perform AdjustTimeZone Time.here

我发现了以下类型签名:

-- ∵
AdjustTimeZone :  Zone -> Msg
here           :                  Task x     Zone
perform        : (a    -> msg) -> Task Never a    -> Cmd msg 
-- ∴
perform AdjustTimeZone here :                        Cmd Msg

怎么可能Task x Zone统一到Task Never a?尤其是,xtoNever是可疑的,而Zoneto是a合理的。

标签: type-inferenceelm

解决方案


我不是类型推理专家,但我认为说“x统一到Never”是不正确的,并且怀疑这是您困惑的根源。x并且a都是类型变量,它们将统一任何一种方式,除非有其他约束发生冲突。所以就像a变成Zonex变成Never,而不是相反。

您可能还想知道为什么Time.here有类型Task x Zone而不是Task Never Zone因为毕竟它here应该知道它是否会出错。我认为这是因为 1)它无关紧要(对于类型系统,尽管它对用户来说肯定可能),以及 2)它使它更容易组合。

因此,假设您想Time.here与其他一些Task可能出错的序列进行排序。Task.andThen具有(错误)类型变量在所有s中都相同(a -> Task x b) -> Task x a -> Task x b的类型。所以如果s 类型是,我们必须提供一个函数。这显然行不通。xTaskTime.hereTask Never ZoneandThenZone -> Task Never b

我很确定您可以这样做TasK.here |> Task.mapError never |> Task.andThen (\zone -> ...),但如果错误类型保留为类型变量而不是被限制为Never. 这不是问题,因为Task.here不会产生任何xs,所以它统一为什么并不重要。


推荐阅读