You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何两个相似Haskell函数定义中as模式的类型推断存在差异?

Why do left and left' have different type signatures in Haskell?

这是个非常有意思的类型推断细节问题!核心原因就在于你在left'的第二个分支里用了as模式(r@(Right _)),这给Haskell的类型检查器加上了额外的约束,而left的实现没有这个限制。

先拆解left的类型推断逻辑

我们一步步看left的定义:

left f (Left x) = Left (f x)
left _ (Right x) = Right x
  1. 第一个分支:输入是Left x,我们暂时把x的类型记为t,所以输入的Either整体是Either t b;f x会生成一个新值,我们把它的类型记为a,所以f的类型是t -> a,返回的Left (f x)类型就是Either a b。
  2. 第二个分支:输入是Right x(x的类型是b),直接返回Right x——这里的Right x类型是Either a b,其中a只需要和第一个分支返回的类型一致就行,完全不需要和输入的Either的Left部分类型(t)绑定。
  3. 综合两个分支,类型检查器就能推断出最通用的类型:left :: (t -> a) -> Either t b -> Either a b,这个类型允许f把t类型转换成任意a类型,灵活性拉满。

再看left'的类型限制来源

现在看left'的定义:

left' f (Left x) = Left (f x)
left' _ r@(Right _) = r

关键差异就在第二个分支的r@(Right _):你直接返回了输入的r,这意味着函数返回的Either类型必须和输入的Either类型完全一致。

  1. 第一个分支:输入的Either是Either a b(x的类型是a),f x必须生成a类型的值——因为返回的Left (f x)要和第二个分支返回的r(类型Either a b)的Left部分类型匹配。
  2. 这就直接限制了f的类型只能是a -> a(输入输出必须是同一种类型),不然Left (f x)的类型就会和r的类型冲突。
  3. 所以类型检查器只能推断出更严格的类型:left' :: (a -> a) -> Either a b -> Either a b,这个类型把f限制成了同类型转换函数。

验证一下这个约束

如果强行给left'指定left的通用类型,编译器会直接报错:

-- 尝试给left'指定更通用的类型,编译失败
left' :: (t -> a) -> Either t b -> Either a b
left' f (Left x) = Left (f x)
left' _ r@(Right _) = r

错误信息会明确提示:Either t b和Either a b无法统一,因为你返回了输入的r(类型Either t b),但函数签名要求返回Either a b,只有当t=a时才能满足这个约束。

内容的提问来源于stack exchange,提问作者Z-Y.L

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:36:07