在 Haskell 中,是否可以为部分应用的多参数类型 class 提供默认实现?
In Haskell, is it possible to provide default implementation for partially applied multi-param type class?
例如,我有一个类型 class :
class MyClass a b c where
fun01 :: a -> b
fun02 :: a -> c
fun03 :: a -> b -> c -> ()
fun04 :: a -> WhatEver
我想为我提供一个默认实现,我们称它为 BaseDataType
,它根据自身以及 fun01
和 [=18= 定义 fun03
的实现].然后我会有这样的东西:
class MyClass BaseDataType b c where
fun03 = fun01 <$> fun02 ...
fun04 = fun02 ...
而不是完成我的 class 实例并避免 fun03
和 fun04
的所有样板代码我只提供 fun01
和 fun02
像这样:
instance MyClass BaseDataType Int Char where
fun01 = 1
fun02 = 'C'
是否可能有某种允许这种行为的语言扩展?我找不到关于这个主题的任何内容。
没有这样的扩展,但您只需将 class 拆分为两个 classes 即可实现此功能:
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'
您 class 的用户不受影响;他们可以在之前使用 MyClass
的地方继续使用 MyClass2
,并获得完全相同的功能。
旁白:MyClass
的原始定义以及 MyClass1
和 MyClass2
甚至由于几个不明确的类型错误而无法编译(c
中未提及fun01
的类型等)- 我假设这个 class 只是为了演示目的而定义的,我没有尝试修复它。
您可以像这样使用 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 ...
例如,我有一个类型 class :
class MyClass a b c where
fun01 :: a -> b
fun02 :: a -> c
fun03 :: a -> b -> c -> ()
fun04 :: a -> WhatEver
我想为我提供一个默认实现,我们称它为 BaseDataType
,它根据自身以及 fun01
和 [=18= 定义 fun03
的实现].然后我会有这样的东西:
class MyClass BaseDataType b c where
fun03 = fun01 <$> fun02 ...
fun04 = fun02 ...
而不是完成我的 class 实例并避免 fun03
和 fun04
的所有样板代码我只提供 fun01
和 fun02
像这样:
instance MyClass BaseDataType Int Char where
fun01 = 1
fun02 = 'C'
是否可能有某种允许这种行为的语言扩展?我找不到关于这个主题的任何内容。
没有这样的扩展,但您只需将 class 拆分为两个 classes 即可实现此功能:
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'
您 class 的用户不受影响;他们可以在之前使用 MyClass
的地方继续使用 MyClass2
,并获得完全相同的功能。
旁白:MyClass
的原始定义以及 MyClass1
和 MyClass2
甚至由于几个不明确的类型错误而无法编译(c
中未提及fun01
的类型等)- 我假设这个 class 只是为了演示目的而定义的,我没有尝试修复它。
您可以像这样使用 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 ...