Haskell无法从Context错误中推断出......

mut*_*gan 8 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 _ 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)之外,您不能实现,因此您必须告诉全世界您实际上正在使用TU.

另一种方法是创建X一个多参数类型的类,

{-# LANGUAGE MultiParamTypeClasses #-}

class (A a, B b) => X x a b where
    method :: x -> a -> b
Run Code Online (Sandbox Code Playgroud)

但是,这可能需要功能依赖来解析实例.另一种方法是使用相关类型,

{-# 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 ...
Run Code Online (Sandbox Code Playgroud)