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

时间:2017-12-18 16:01:44

标签: haskell default typeclass multiparameter

例如,我有一个类型类:

class MyClass a b c where
    fun01 :: a -> b
    fun02 :: a -> c

    fun03 :: a -> b -> c -> ()
    fun04 :: a -> WhatEver

我想为我提供一个默认的实现,让我们称之为BaseDataType,它定义fun03的实现自我和fun01fun02。然后我会有这样的事情:

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

而不是最终确定我的类实例并避免fun03fun04的所有样板代码我只需提供fun01fun02,如下所示:< / p>

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

是否可能有某种语言扩展允许这种行为?我无法找到关于这个话题的任何内容。

2 个答案:

答案 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的原始定义,MyClass1MyClass2甚至无法编译,因为有几个模棱两可的类型错误(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 ...