如何在Haskell的子类定义中定义默认实现? [英] How to define default implementation in subclass definition in Haskell?
问题描述
我是Haskell的新成员,以下是我的问题:给出这个类的
:
class MyClass a where
foo :: a - > [a]
然后我有一个更具体的子类:
class(MyClass a)=> SubClass a where
foo param = [bar param]
bar :: a - > a
但它无法按预期工作。我期待在 SubClass
的定义中设置一个默认实现,但它不会。我将需要单独为 MyClass
定义实例,但这听起来很愚蠢。当我知道某个子类完全满足某些属性时,我该如何实现默认实现?
更具体地说,我想在Haskell中表示类满足一些属性,其父类的一些函数可以具有默认实现
。在我的例子中, SubClass
有属性 bar
,这样我知道 foo
肯定是以这种方式定义的。
这个问题的更一般形式是,使用类和实例重用是个好主意吗?
我发现这篇文章:在Haskell中包含使用默认实现的类型类型
它非常接近,但仍然没有完全回答我的问题,它们的形式有点不同。
在Daniel的答案中详细阐述:
假设你有一个新的数据类型 MyData
,定义为
data MyData = D1 | D2
您想让 MyData
一个实例 SubClass
。您首先尝试显而易见的解决方案。
instance SubClass MyData其中
bar x = case x of {D1 - > D2; D2 - > D1}
然而,对类型签名的快速检查表明,这不起作用,因为在它可以是 SubClass
的实例之前,类型必须是 MyClass
的实例。因此,您可以使 MyData
MyClass
的一个实例。
instance MyClass MyData
同样,这会产生一个错误, code> foo 包含在 MyClass
的最小完整定义中。为了您的实例能够工作,您必须手动定义 foo
,从而破坏默认声明的目的。
简而言之,在基本的Haskell98(或者Haskell2010)中没有办法做到这一点。然而,幸运的是,GHC提供了一个有用的扩展,名为 DefaultSignatures
。所以,使用Daniel的例子:
{ - #LANGUAGE DefaultSignatures# - }
class MyClass a where
foo :: a - > [a]
default foo :: SubClass a => a - > [a]
foo param = [param]
class MyClass a => SubClass a where
bar :: a - > a
现在,您可以定义这些实例,并且它们将按照您的预期工作。该解决方案的缺点是必须在 MyClass
中定义默认定义,但这是必需的。 foo
的定义属于 MyClass
(或它的一个实例声明)的定义,所以如果你能在 SubClass
,Haskell的类型隔离定义中定义默认声明 foo
被打破。
I am new comer of Haskell and following is my question:
given this class:
class MyClass a where
foo :: a -> [a]
then I have a subclass that is more specific:
class (MyClass a) => SubClass a where
foo param = [bar param]
bar :: a -> a
but it doesn't work as expected. I was expecting a default implementation is setup in the definition of SubClass
but it doesn't. I will need to define the instance for MyClass
seperately, but that sounds stupid. How can I achieve default implementation when I know some subclass satisfies some property definitely?
More specifically, I want to express in Haskell, that when a class satisfies some properties, some functions for its parent can have default implementation
. In my example, SubClass
has property bar
such that I know foo
is definitely defined in such a way.
A more general form of this question is, is it a good idea to reuse by using classes and instances?
I found this post: Inclusion of typeclasses with default implementation in Haskell
It's quite close, but still not answering my question totally and their forms are little bit different.
Elaborating on Daniel's answer:
Suppose you have a new datatype MyData
, defined as
data MyData = D1 | D2
You want to make MyData
an instance of SubClass
. You try the obvious solution first.
instance SubClass MyData where
bar x = case x of { D1 -> D2 ; D2 -> D1 }
A quick examination of the type signatures, though, reveals that this won't work, because a type has to be an instance of MyClass
before it can be an instance of SubClass
. So you make MyData
an instance of MyClass
.
instance MyClass MyData
Again, this raises an error, because foo
is included in the minimal complete definition of MyClass
. For your instance to work, you would have to manually define foo
, thus defeating the purpose of the default declaration.
In short, there is no way to do this in basic Haskell98 (or Haskell2010, for that matter). Thankfully, however, GHC provides a useful extension called DefaultSignatures
. So, using Daniel's example:
{-# LANGUAGE DefaultSignatures #-}
class MyClass a where
foo :: a -> [a]
default foo :: SubClass a => a -> [a]
foo param = [param]
class MyClass a => SubClass a where
bar :: a -> a
And now, you can define the instances and they will work as you would expect. The downside to this solution is that the default definition has to be defined in MyClass
, but this is necessary. The definition of foo
belongs to the definition of MyClass
(or one of its instance declarations), so if you were able to define the default declaration of foo
within the definition of SubClass
, Haskell's type isolation would be broken.
这篇关于如何在Haskell的子类定义中定义默认实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!