gpt4 book ai didi

haskell - MultiParamTypeClasses - 为什么这个类型变量不明确?

转载 作者:行者123 更新时间:2023-12-04 18:18:46 27 4
gpt4 key购买 nike

假设我定义了 multi-parameter type class :

{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes, FlexibleContexts, FlexibleInstances #-}

class Table a b c where
decrement :: a -> a
evalutate :: a -> b -> c

然后我定义一个使用 decrement 的函数,为简单起见:
d = decrement

当我尝试在 ghci 中加载它时(版本 8.6.3):
• Could not deduce (Table a b0 c0)
arising from a use of ‘decrement’
from the context: Table a b c
bound by the type signature for:
d :: forall a b c. Table a b c => a -> a
at Thing.hs:13:1-28
The type variables ‘b0’, ‘c0’ are ambiguous
Relevant bindings include d :: a -> a (bound at Thing.hs:14:1)
These potential instance exist:
instance Table (DummyTable a b) a b

这让我很困惑,因为 d 的类型正是 decrement 的类型,在类声明中表示。

我想到了以下解决方法:
data Table a b = Table (a -> b) ((Table a b) -> (Table a b))

但这似乎在符号上不方便,而且我也只是想知道为什么我首先会收到此错误消息。

最佳答案

问题是,由于 decrement只需要 a类型,无法确定哪些类型 bc应该是,即使在调用函数的时候(从而将多态性解决为特定类型) - 因此,GHC 将无法决定使用哪个实例。

例如:假设您有两个 Table 实例:Table Int String Bool , 和表 Int Bool Float ;你调用你的函数d在应该将一个 Int 映射到另一个 Int 的上下文中 - 问题是,它匹配两个实例! ( a 两者都是 Int )。

注意,如果你让你的函数等于 evalutate :

d = evalutate

然后编译器接受它。这是因为,由于 evalutate取决于三个类型参数 a、b 和 c,调用站点的上下文将允许明确的实例解析 - 只需在调用它的位置检查 a、b 和 c 的类型。

当然,对于单参数类型类来说,这通常不是问题——只有一种类型需要解决;当我们处理多个参数时,事情变得复杂......

一种常见的解决方案是使用 functional dependencies - 制作 bc取决于 a :

 class Table a b c | a -> b c where
decrement :: a -> a
evalutate :: a -> b -> c

这告诉编译器,对于给定类型的每个 Table 实例 a ,只有一个实例( bc 将由 a 唯一确定);所以它会知道不会有任何歧义并接受您的 d = decrement高兴地。

关于haskell - MultiParamTypeClasses - 为什么这个类型变量不明确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56487391/

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