[英]Haskell “could not deduce” error
I have the following code: 我有以下代码:
class Coll c e where
map :: (e1 -> e2) -> c e1 -> c e2
merge :: (e -> e -> e) -> e -> c e -> e
sum :: (Num e) => c e -> e
sum = merge (+) 0
So far so good. 到现在为止还挺好。 But then I have:
但是然后我有:
sumMap :: (Num e2) => (e1 -> e2) -> c e1 -> e2
sumMap f c = (merge (+) 0) (map f c)
Compiling gives an error: 编译产生错误:
Could not deduce (Coll c e2) arising from a use a 'merge' from the context (Coll ce) [...] Possible fix: add (Coll c e2) to the context of the type signature for sumMap [...]
无法从上下文(Coll ce)推断出由于使用“合并”而引起的(Coll c e2)[...]可能的解决方法:将(Coll c e2)添加到sumMap [...的类型签名的上下文中]
So I replace sumMap :: (Num e2) => (e1 -> e2) -> c e1 -> e2
with sumMap :: (Num e2, Coll c e2) => (e1 -> e2) -> c e1 -> e2
, but then it gives another error: 所以我将
sumMap :: (Num e2) => (e1 -> e2) -> c e1 -> e2
sumMap :: (Num e2, Coll c e2) => (e1 -> e2) -> c e1 -> e2
sumMap :: (Num e2) => (e1 -> e2) -> c e1 -> e2
替换为sumMap :: (Num e2, Coll c e2) => (e1 -> e2) -> c e1 -> e2
sumMap :: (Num e2) => (e1 -> e2) -> c e1 -> e2
sumMap :: (Num e2, Coll c e2) => (e1 -> e2) -> c e1 -> e2
,但随后又出现另一个错误:
Could not deduce (Coll c e0) arising from a use of 'map' from the context (Coll ce) [...] Possible fix: add a type signature that fixes these type variable(s) [...]
无法从上下文(Coll ce)推断出由于使用“ map”而引起的(Coll c e0)[...]可能的解决办法:添加类型签名以修复这些类型变量[...]
I'm confused, so I comment out the definition for sumMap
, and run :t (merge (+) 0) . (map (* 2))
我很困惑,所以我注释掉了
sumMap
的定义,然后运行:t (merge (+) 0) . (map (* 2))
:t (merge (+) 0) . (map (* 2))
, which gives me [...] :: (Num c, Coll c1 c, Coll c1 e) => c1 c -> c
. :t (merge (+) 0) . (map (* 2))
,这给了我[...] :: (Num c, Coll c1 c, Coll c1 e) => c1 c -> c
。 Ignoring how it mangled my variables' names, Coll c1 e
is bizarre; Coll c1 e
忽略了变量名称的混乱方式,这很奇怪。 e
is not even used in the definition!, so why is it there!? e
甚至没有在定义中使用!!为什么在其中!! Anyways, then I run ((merge (+) 0) . (map (* 2))) [1,2,3,4]
, which successfully returns 20
. 无论如何,然后我运行
((merge (+) 0) . (map (* 2))) [1,2,3,4]
,它成功返回20
。 What's going on here? 这里发生了什么? Why does this function work only when I don't try to tie it to a name?
为什么仅当我不尝试将其绑定到名称时,此功能才起作用?
Your problems stems from the way you defined your Col
class. 您的问题源于您定义
Col
类的方式。 In particular, the class definition includes both types c
and e
. 特别地,所述类定义包括两种类型
c
和 e
。 This means that you can have different instances for different types of elements—presumably not what you want. 这意味着您可以为不同类型的元素使用不同的实例,大概不是您想要的。 Instead, you want to have a single instance for each possible
c
that works with any type of element at all. 相反,您想为所有可能与任何类型的元素一起使用的
c
提供一个实例。
It would be better to write the class as: 最好将类编写为:
class Coll c where
map :: (e1 -> e2) -> c e1 -> c e2
merge :: (e -> e -> e) -> e -> c e -> e
sum :: Num e => c e -> e
sum = merge (+) 0
Now each individual instance only depends on c
, not the type of its elements. 现在,每个单独的实例仅取决于
c
,而不取决于其元素的类型。
I suspect that you wrote class Coll ce where
because you wanted to ensure that c
was a collection of elements. 我怀疑您
class Coll ce where
编写了class Coll ce where
因为您想确保c
是元素的集合。 (Like writing C<E>
in Java.) However, this is unnecessary in Haskell: a type variable like c
can stand in for parameterized types with no other annotation. (就像用Java编写
C<E>
一样。)但是,这在Haskell中是不必要的:像c
这样的类型变量可以代替其他注释而代表参数化类型。 The type system will figure out that c
takes a parameter by the way you use it in the signatures for map
, merge
and so on. 类型系统将确定
c
通过在map
, merge
等的签名中使用参数来采用参数。
Since this is unnecessary, class Coll ce
means that the class is based on two different type variables, which don't even have to be related. 由于这是不必要的,因此
class Coll ce
表示该类基于两个不同的类型变量,它们甚至不必关联。 This means that, to figure out which instance to use, the type system needs to know the specific type for both the collection and its elements, and in your specific case it does not have enough information to do this. 这意味着,要弄清楚要使用的情况下,该类型系统需要知道的收集和它的因素,其中包括特定类型,并在特定的情况下,它没有足够的信息来做到这一点。 If you just leave
e
out of the class definition, it should not be a problem. 如果只将
e
排除在类定义之外,那应该不是问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.