How to define default implementation in subclass definition in Haskell?

天涯浪子 提交于 2020-01-15 07:02:14

问题


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.


回答1:


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.




回答2:


This can be achieved with DefaultSignatures:

{-# 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

Testing it in ghci:

> instance MyClass Integer; instance SubClass Integer where bar = id
> foo 3
[3]


来源:https://stackoverflow.com/questions/31600470/how-to-define-default-implementation-in-subclass-definition-in-haskell

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!