我有类型类,对于所有这些类我都希望有一些常见的行为.我的问题在以下代码中解释:
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,我该如何编写这个部分?
Dan*_*her 11
签名method :: (A a, B b) =>  x -> a -> b承诺method适用于具有实例和实例的每对类型,但您将其定义为仅适用于两种特定类型.(a, b)aAbB
这与Java等中的接口根本不同,其中被调用者选择使用哪种类型,调用者唯一知道的是接口X被实现.在Haskell中,给定这样的签名,调用者决定使用哪些类型(这里,作为第二个参数传递什么类型以及应返回什么类型)并且被调用者必须能够提供所需的功能(只要需要) types是所需类的实例.
如果没有类中的任何方法A并且B分别分析该类的实例的构造值,则method除了undefined(因为可能存在不同程度的未定义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 ...