e2) -> c e1 -> c e2 merge :: (e -> e -> e) -> e --6ren">
gpt4 book ai didi

function - haskell "could not deduce"错误

转载 作者:行者123 更新时间:2023-12-01 19:18:57 26 4
gpt4 key购买 nike

我有以下代码:

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

到目前为止一切顺利。但后来我有:

    sumMap :: (Num e2) => (e1 -> e2) -> c e1 -> e2
sumMap f c = (merge (+) 0) (map f c)

编译出现错误:

Could not deduce (Coll c e2) arising from a use a 'merge' from the context (Coll c e) [...] Possible fix: add (Coll c e2) to the context of the type signature for sumMap [...]

所以我用 sumMap::(Num e2, Coll c e2) 替换 sumMap::(Num e2) => (e1 -> e2) -> c e1 -> e2 => (e1 -> e2) -> c e1 -> e2,但随后又出现另一个错误:

Could not deduce (Coll c e0) arising from a use of 'map' from the context (Coll c e) [...] Possible fix: add a type signature that fixes these type variable(s) [...]

我很困惑,所以我注释掉了 sumMap 的定义,并运行 :t (merge (+) 0) 。 (map (* 2)),它给出了 [...]::(Num c, Coll c1 c, Coll c1 e) => c1 c -> c。忽略它如何破坏我的变量名称,Coll c1 e 很奇怪; e 甚至没有在定义中使用!那为什么它会在那里!?无论如何,然后我运行 ((merge (+) 0) .(map (* 2))) [1,2,3,4],成功返回 20 。这里发生了什么?为什么这个函数只有在我不尝试将其与名称绑定(bind)时才起作用?

最佳答案

您的问题源于您定义 Col 的方式类(class)。特别是,类定义包括两种类型 c e 。这意味着您可以为不同类型的元素拥有不同的实例——这可能不是您想要的。相反,您希望为每个可能的 c 拥有一个实例。适用于任何类型的元素。

最好将类编写为:

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

现在每个单独的实例仅依赖于 c ,而不是其元素的类型。

我怀疑你写的是class Coll c e where因为您想确保c是元素的集合。 (就像在 Java 中写 C<E> 一样。)然而,这在 Haskell 中是不必要的:像 c 这样的类型变量。可以代表没有其他注释的参数化类型。类型系统会计算出 c按照您在 map 的签名中使用参数的方式获取参数, merge等等。

由于这是不必要的,class Coll c e意味着该类基于两个不同类型变量,它们甚至不必相关。这意味着,要确定要使用哪个实例,类型系统需要知道集合及其元素的特定类型,而在您的特定情况下,它没有足够的信息来执行此操作。如果你就离开e在类定义之外,这应该不是问题。

关于function - haskell "could not deduce"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27453235/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com