haskell - 为什么在两个相似的函数定义中类型推断与 as-pattern 的差异?

标签 haskell type-signature

我有以下两个类似的函数定义:

left f (Left x) = Left (f x)
left _ (Right x) = Right x

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

当我检查这两个函数的类型签名时,我对以下类型感到困惑:
ghci> :t left
left :: (t -> a) -> Either t b -> Either a b
ghci> :t left'
left' :: (a -> a) -> Either a b -> Either a b

我想leftleft'应该是相同的类型签名,但是 haskell 的类型推断给了我一个惊喜。

我不知道为什么 left 的类型签名和 left'是不同的。谁能给我一些信息?谢谢!

最佳答案

left' 的第二行:

left' _ r@(Right _) = r
--      ^^^^^^^^^^^   ^

由于您使用 as 模式,因此您需要输入类型等于返回类型,因为显然它们是完全相同的值。 left'的类型然后被限制为 a -> b -> b 形式的东西。 .

然后这个限制向后传播,反过来又限制了函数的类型——希望你能看到如何;这不是太难。

但是,在 left 的第二行中, 你构造了一个新值
left _ (Right x) = Right x
--                 ^^^^^^^

这个新值的类型没有被限制,因此不会出现同样的问题;它可以是 a -> b -> c 的形式,这就是你想要的。

因此,left' 的类型比 left 的类型更受限制,这就是导致它们的类型不相等的原因。

为了更具体地说明这个概念,我将更准确地向您描述这种限制是如何向后传播的。

我们知道 left'的签名格式为 (a -> b) -> Either a q -> Either b q .但是,第 2 行规定 Either a q = Either b q ,这意味着 a = b , 所以类型现在变成了 (a -> a) -> Either a q -> Either a q .

关于haskell - 为什么在两个相似的函数定义中类型推断与 as-pattern 的差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55432131/

相关文章:

haskell - 使用惰性文本和字节字符串处理非常大的文本文件

haskell - 如何在状态 monad 中使用 Debug.Trace.trace?

haskell - 为什么我不能为本地 let bound ST 操作提供显式类型签名

Haskell 类型签名和 Monad

haskell - Haskell 中的任何类型?

java - 在 Android 中使用 XAdeS-BES 进行签名

haskell - Intero:来自堆栈配置的 ghc 不匹配

haskell - 快照框架 : How do I run IO within a handler

haskell - 这种类型的签名发生了什么? (Haskell 中的 Vector.Mutable 修饰符)

haskell - Haskell 函数类型声明中括号的详细信息