在 Haskell 中,是否可以为部分应用的多参数类型类提供默认实现?



例如,我有一个类型类:

class MyClass a b c where
fun01 :: a -> b
fun02 :: a -> c
fun03 :: a -> b -> c -> ()
fun04 :: a -> WhatEver

我想为我的提供一个默认实现,我们称之为BaseDataType,它根据自身和fun01fun02来定义fun03的实现。然后我会有这样的东西:

class MyClass BaseDataType b c where
fun03 = fun01 <$> fun02 ...
fun04 = fun02 ...

除了完成我的类实例并避免所有fun03fun04的样板代码之外,我只提供这样的fun01fun02

instance MyClass BaseDataType Int Char where
fun01 = 1
fun02 = 'C'

是否有一些语言扩展允许这种行为?我找不到有关此主题的任何内容。

没有这样的扩展,但您只需将类拆分为两个类即可实现此功能:

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'

类的用户不受影响;他们可以继续使用以前使用MyClassMyClass2,并获得完全相同的功能。


旁白:MyClass的原始定义,MyClass1MyClass2由于几个模棱两可的类型错误(cfun01类型中没有提到等)甚至没有编译 - 我假设这个类只是为了演示目的而定义的,我没有试图解决这个问题。

你可以像这样使用 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 ...

相关内容

  • 没有找到相关文章

最新更新