我有类型类,对于所有这些类我都希望有一些常见的行为 . 我的问题在以下代码中解释:
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
当我加载此模块时,我收到以下错误:
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.
在这种情况下我无所适从 . 即使T和U是A和B的实例,我也会收到此错误 . 如果我无法从 method
返回刚性类型值,我该如何编写这部分代码?
2 回答
签名
method :: (A a, B b) => x -> a -> b
承诺method
适用于 every 对类型(a, b)
与a
A
的实例和b
B
的实例,但您将其定义为仅适用于两种特定类型 .这与Java等中的接口根本不同,其中被调用者选择使用哪种类型,调用者唯一知道的是接口X被实现 . 在Haskell中,给定这样的签名,调用者决定使用哪些类型(这里,作为第二个参数传递什么类型以及应返回什么类型)并且被调用者必须能够提供所需的功能(只要需要) types是所需类的实例 .
没有类
A
和B
中的任何方法来分别分析该类实例的构造值,除了undefined
之外你不能实现method
(由于seq
可能存在不同程度的未定义),所以你必须告诉全世界你事实上正在使用T
和U
.另一种方法是使
X
成为一个多参数类型的类,但是,这可能需要功能依赖来解析实例 . 另一种方法是使用相关类型,
很难想出一种方法来拯救你的榜样(由于Daniel Fischer提到的原因) . 如果你有两个完全不相关的类型A和B,你应该如何 Build 一般连接?所以你可以将两者放在一起,但我怀疑这是你想要的:
当你想在
A2B T U
旁边有A2B T V
之类的实例时,这个设计就不会出现问题 .