Haskell 哈斯克尔无法推断。。。从上下文错误

Haskell 哈斯克尔无法推断。。。从上下文错误,haskell,Haskell,我有类型类,对于所有类型类,我都希望有一些常见的行为。以下代码解释了我的问题: class A a class B b class X x where method :: (A a, B b) => x -> a -> b data T = L | M | N data U = P | Q | R instance A T instance B U data Y = ZZZ instance X Y where method _ L = P method _

我有类型类,对于所有类型类,我都希望有一些常见的行为。以下代码解释了我的问题:

class A a class B b class X x where method :: (A a, B b) => x -> a -> b data T = L | M | N data U = P | Q | R instance A T instance B U data Y = ZZZ instance X Y where method _ L = P method _ M = Q method _ N = R 甲级 B类 X类X在哪里 方法:(A,B)=>x->A->B 数据T=L | M | N 数据U=P | Q | R 例A T 实例B U 数据Y=ZZZ 实例X Y在哪里 方法L=P 方法M=Q 方法N=R 加载此模块时,出现以下错误:

example.hs:19:14: Could not deduce (a ~ T) from the context (A a, B b) bound by the type signature for method :: (A a, B b) => Y -> a -> b at example.hs:(17,5)-(19,18) `a' is a rigid type variable bound by the type signature for method :: (A a, B b) => Y -> a -> b at example.hs:17:5 In the pattern: N In an equation for `method': method _ N = R In the instance declaration for `X Y' example.hs:19:18: Could not deduce (b ~ U) from the context (A a, B b) bound by the type signature for method :: (A a, B b) => Y -> a -> b at example.hs:(17,5)-(19,18) `b' is a rigid type variable bound by the type signature for method :: (A a, B b) => Y -> a -> b at example.hs:17:5 In the expression: R In an equation for `method': method _ N = R In the instance declaration for `X Y' Failed, modules loaded: none. 示例.hs:19:14: 无法推断(a~T) 从上下文(A,B) 由方法的类型签名绑定::(A,B)=>Y->A->B 例如:hs:(17,5)-(19,18) `a'是一个刚性类型变量,由 方法的类型签名::(A,B)=>Y->A->B 例如:hs:17:5 在模式中:N 在“方法”的方程式中:方法N=R 在'X Y'的实例声明中 示例.hs:19:18: 无法推断(b~U) 从上下文(A,B) 由方法的类型签名绑定::(A,B)=>Y->A->B 例如:hs:(17,5)-(19,18) `b'是一个刚性类型变量,由 方法的类型签名::(A,B)=>Y->A->B 例如:hs:17:5 在表达式中:R 在“方法”的方程式中:方法N=R 在'X Y'的实例声明中 失败,已加载模块:无。
我不知道在这种情况下该怎么办。即使T和U是A和B的实例,我也会得到这个错误。如果我不能从
method
返回一个刚性类型值,我该如何对这部分进行编码?

签名
方法::(a,B)=>x->a->B
承诺
方法
适用于每对
(a,B)类型
使用
a
一个
a
的实例和
b
一个
b
的实例,但您将其定义为仅适用于两种特定类型

这与Java或类似语言中的接口有根本不同,在Java或类似语言中,被调用方选择使用哪种类型,调用方只知道实现了接口X。在Haskell中,给定这样一个签名,调用者决定使用哪些类型(这里,什么类型作为第二个参数传递,什么类型应该返回),被调用者必须能够提供所需的功能(只要所需的类型是所需类的实例)

如果类
A
B
中没有任何方法来分别分析该类实例的构造值,则除了使用
未定义的
之外,您无法实现
方法
(由于
seq
,可能存在不同程度的未定义),因此,你必须告诉世界,你实际上在使用
T
U

另一种方法是使
X
成为一个多参数类型的类

{-# LANGUAGE MultiParamTypeClasses #-}

class (A a, B b) => X x a b where
    method :: x -> a -> b
但是,这可能需要函数依赖关系来解析实例。另一种方法是使用关联类型

{-# LANGUAGE TypeFamilies #-}

class X x where
    type AType x
    type BType x
    method :: x -> AType x -> BType x

instance X Y where
    type AType Y = T
    type BType Y = U
    method ...

真的很难想出一个拯救你的例子的方法(出于丹尼尔·菲舍尔提到的原因)。如果您有两个完全不相关的类型类A和B,您应该如何建立一般连接?所以你可以把两者结合起来,但我怀疑这是你想要的:

{-# LANGUAGE MultiParamTypeClasses #-}

class A2B a b where
  convert :: a -> b

data T = L | M | N
data U = P | Q | R

instance A2B T U where
  convert L = P
  convert M = Q
  convert N = R  

data Y = ZZZ

class X x where
    method :: (A2B a b) =>  x -> a -> b

instance X Y where
    method _ t = convert t

而且这种设计也不是很稳定:当你想在
a2btu
旁边有像
a2btv
这样的实例时,你会遇到麻烦

我明白你的意思了。我有类型类Y,T,U一起工作。我还有一个三元组类型的类Y1,T1,U1,它们一起工作。在我的问题中,这些类型类形成了模型的实例。我希望有一个通用的代码可以在这些模型上工作,而不必关心它们是如何实现的。谢谢你指出了这个问题。这种代码在类似java的语言中也是一个问题。感谢您的解释。MultiparamTypeClass和函数依赖关系解决了我的问题。好。:)