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

Rey*_*och 10 haskell default multiparameter typeclass

例如,我有一个类型类:

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

    fun03 :: a -> b -> c -> ()
    fun04 :: a -> WhatEver
Run Code Online (Sandbox Code Playgroud)

我想为我提供一个默认实现,让我们调用它BaseDataType来定义fun03自我和fun01和的实现fun02.然后我会有这样的事情:

class MyClass BaseDataType b c where
    fun03 = fun01 <$> fun02 ...
    fun04 = fun02 ...
Run Code Online (Sandbox Code Playgroud)

而不是完成我的类实例并避免所有的样板代码fun03,fun04我只是提供fun01fun02喜欢这样:

instance MyClass BaseDataType Int Char where
    fun01 = 1
    fun02 = 'C'
Run Code Online (Sandbox Code Playgroud)

是否可能有一些语言扩展允许这种行为?我在这个主题上找不到任何东西.

use*_*038 11

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

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

然后您的实例将按您希望的方式工作:

-- 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'
Run Code Online (Sandbox Code Playgroud)

班级用户不受影响; 他们可以继续消费以前使用的MyClass2地方MyClass并获得完全相同的功能.


旁白:原来的定义MyClass,并MyClass1MyClass2甚至不编译由于一些不明确的类型错误(c在类型没有被提及fun01,等) -我认为这个类的定义只是为了演示的目的,我还没有试过解决这个问题.


Ale*_*nko 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 ...
Run Code Online (Sandbox Code Playgroud)

  • +1,但我不认为这对于OP是可用的,因为默认是_for all_`Myclass`实例,而不仅仅是'MyClass BaseDataType`特化.(在其他情况下,默认实现只会给出一个模糊的类型错误,以指示必须替换自定义实例.) (2认同)