我一直在尝试从this question的答案中找到一个小例子:
liftTup :: (x -> f x) -> (a, b) -> (f a, f b)
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v)
这显然需要forall
量词才能工作,但我正在尝试理解错误消息语法,以便能够知道如果我将来会遇到类似的错误。所以我得到了这个:
monad.hs:112:28-37: Couldn't match type `x' with `b' …
`x' is a rigid type variable bound by
the type signature for
liftTup :: (x -> f x) -> (a, b) -> (f a, f b)
at /Users/user/monad.hs:111:12
`b' is a rigid type variable bound by
the type signature for
liftTup :: (x -> f x) -> (a, b) -> (f a, f b)
at /Users/user/monad.hs:111:12
Expected type: f a
Actual type: f x
In the return type of a call of `liftFunc'
In the expression: liftFunc t
In the expression: (liftFunc t, liftFunc v)
monad.hs:112:40-49: Couldn't match type `a' with `b' …
`a' is a rigid type variable bound by
the type signature for
liftTup :: (x -> f x) -> (a, b) -> (f a, f b)
at /Users/user/monad.hs:111:12
`b' is a rigid type variable bound by
the type signature for
liftTup :: (x -> f x) -> (a, b) -> (f a, f b)
at /Users/user/monad.hs:111:12
Expected type: f b
Actual type: f x
In the return type of a call of `liftFunc'
In the expression: liftFunc v
In the expression: (liftFunc t, liftFunc v)
据我所知,第一个错误与第一次将liftFunc
应用于t
有关,因此会尝试将f x
与f a
匹配。但b
如何与此相关? b
仅出现在元组的第二个元素中。
我猜测的第二个错误来自a
与之前的x
应用中liftFunc
匹配的事实,现在我们尝试将其与b
匹配在第二个,但这不是很有效。这是对的吗?
读取这些错误消息的正确方法是什么?“无法匹配类型..与...”中提到的变量之间的关系是什么?“预期类型:..实际类型:..”消息中提到的变量是什么?
答案 0 :(得分:4)
您正在正确阅读类型错误:
liftFunc t
liftFunc
此应用程序的返回类型为f x
f a
f x
和f a
属于同一类型; GHC在试图证明要求x
和b
是同一件事时失败了“期望类型”和“实际类型”与之后立即讨论的表达式的类型相关(“在对liftFunc
的调用的返回类型...”中)。但是“无法将类型'x'与'b'匹配”告诉你它注意到的事情是不可能的,当试图将预期的类型与实际类型相匹配时,所以它不一定直接报告那个两者不匹配。
这可能不直观,但它是有效的。由于liftFunc
在 liftTup
中具有单形类型,并且它适用于a
和b
两种类型的值,因此类型检查器会推断出x
,a
和b
必须完全相同。所以x ~ b
(~
是如何在Haskell中编写类型相等)实际上必须保持这一点是一个良好类型的表达式,并确定它不能统一(通过观察x
和b
都是必须保持独立普遍量化的“刚性类型变量”确定确定存在类型错误。
我的猜测是类型检查器已经做了一些分析以得出一组成对约束,包括f x ~ f a
,f x ~ f b
,x ~ a
, x ~ b
和a ~ b
,然后开始证明他们。也许x ~ b
只是它尝试过的第一个。或许它必须证明x ~ a
,并且没有直接的方法来证明这一点,并且唯一可用的其他信息是a ~ b
它尝试应用它来导出x ~ b
,然后无法证明(并且循环检查阻止它应用b ~ a
再次以x ~ a
结束)它在那时失败。无论如何,沿着这些方向的东西。我很漂亮x ~ b
只是在尝试检查liftFunc t
的过程中发现的第一件事是不可能的。
答案 1 :(得分:2)
这些错误完全描述了您的问题。但阅读ghc错误消息有时很困难,因为它们包含如此多的信息。
Couldn't match type x with b
表示它希望x
和b
属于同一类型,但无法证明这一点。同样地,对于另一个错误。所以从两个错误一起,你知道编译器期望a==b==x
,但这不是你写的。
但是你不知道为什么它确实期待这个。第一条错误消息说明如下:
Expected type: f a
Actual type: f x
In the return type of a call of `liftFunc'
您声称liftunc
的类型为x -> f x
。但是,您还声称liftFunc t
的类型为f a
。从这一点来看,编译器可以推断的{em>仅事物a
和x
必须是同一类型。但是没有办法证明,因此,输入错误。
第二个错误是将完全相同的逻辑应用于元组的第二个参数。