例如,我有一个类型类:
class MyClass a b c where
fun01 :: a -> b
fun02 :: a -> c
fun03 :: a -> b -> c -> ()
fun04 :: a -> WhatEver
我想为我提供一个默认的实现,让我们称之为BaseDataType
,它定义fun03
的实现自我和fun01
和fun02
。然后我会有这样的事情:
class MyClass BaseDataType b c where
fun03 = fun01 <$> fun02 ...
fun04 = fun02 ...
而不是最终确定我的类实例并避免fun03
和fun04
的所有样板代码我只需提供fun01
和fun02
,如下所示:< / p>
instance MyClass BaseDataType Int Char where
fun01 = 1
fun02 = 'C'
是否可能有某种语言扩展允许这种行为?我无法找到关于这个话题的任何内容。
答案 0 :(得分:10)
没有这样的扩展,但只需将您的类拆分为两个类就可以实现此功能:
class MyClass1 a b c where
fun03 :: a -> b -> c -> ()
fun04 :: a -> WhatEver
class MyClass1 a b c => MyClass2 a b c where
fun01 :: a -> b
fun02 :: a -> c
然后您的实例将以您想要的方式运行:
-- NB: need the MyClass2 constraint if you use `fun01` or `fun02` in the definitions
-- This requires UndecidableInstances
instance MyClass2 BaseDataType b c => MyClass1 BaseDataType b c where
fun03 = fun01 <$> fun02 ...
fun04 = fun02 ...
instance MyClass2 BaseDataType Int Char where
fun01 = 1
fun02 = 'C'
班级用户不受影响;他们可以继续使用MyClass2
之前使用MyClass
并获得完全相同的功能。
除此之外:MyClass
的原始定义,MyClass1
和MyClass2
甚至无法编译,因为有几个模棱两可的类型错误(c
未提及fun01
的类型等等 - 我认为这个类只是出于演示目的而定义的,我还没有尝试解决这个问题。
答案 1 :(得分:5)
您可以像这样使用DefaultSignatures
class MyClass a b c where
fun01 :: a -> b
fun02 :: a -> c
fun03 :: a -> b -> c -> ()
default fun03 :: (a ~ BaseDataType) => a -> b -> c -> ()
fun03 = fun01 <$> fun02 ...
fun04 :: a -> WhatEver
default fun04 :: (a ~ BaseDataType) => a -> WhatEver
fun04 = fun02 ...