我有类型类,对于所有这些类我都希望有一些常见的行为.我的问题在以下代码中解释:
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
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)