Does every superclass need to be specified in the context of the class declaration class?

The ArrowList class ArrowList has the following declaration:

class (Arrow a, ArrowPlus a, ArrowZero a, ArrowApply a) => ArrowList a where ...

The ArrowPlus class ArrowPlus declared as: class ArrowZero a => ArrowPlus a where ...

The ArrowZero class ArrowZero declared as: class Arrow a => ArrowZero a where ...

And the ArrowApply class ArrowApply declared as: class Arrow a => ArrowApply a where ...

Why can't it just be written as: class (ArrowPlus a, ArrowApply a) => ArrowList a where ...?

+7
source share
1 answer

No, there is no need to include all superclasses. If you write

 class (ArrowPlus a, ArrowApply a) => ArrowList a where 

he will work. However, there are two possible reasons for explicitly mentioning all superclasses.

  • This may be more readable, as you can immediately understand what all superclasses are.

  • This might be a little more efficient, because explicitly listing the superclasses will lead to a direct search for the dictionary at runtime, whereas for a transitive superclass, it first searches for the dictionary for the superclass, and then searches for the class member in that.

    For example, take this inheritance chain:

     module Example where class Foo a where foo :: a -> String class Foo a => Bar a class Bar a => Baz a class Baz a => Xyzzy a quux :: Xyzzy a => a -> String quux = foo 

    Looking at the generated kernel for this (with ghc -c -ddump-simpl ), we see that this generates a chain of search calls. First he searches for a dictionary for Baz in Xyzzy , then Bar in it, then Foo and finally he can search for Foo .

     Example.quux :: forall a_abI. Example.Xyzzy a_abI => a_abI -> GHC.Base.String [GblId, Arity=1, Caf=NoCafRefs] Example.quux = \ (@ a_acE) ($dXyzzy_acF :: Example.Xyzzy a_acE) -> Example.foo @ a_acE (Example.$p1Bar @ a_acE (Example.$p1Baz @ a_acE (Example.$p1Xyzzy @ a_acE $dXyzzy_acF))) 

    By changing the definition of Xyzzy to explicitly indicate Foo :

     class (Foo a, Baz a) => Xyzzy a 

    We see that now he can get the Foo dictionary directly from Xyzzy and look for Foo in this.

     Example.quux :: forall a_abD. Example.Xyzzy a_abD => a_abD -> GHC.Base.String [GblId, Arity=1, Caf=NoCafRefs] Example.quux = \ (@ a_acz) ($dXyzzy_acA :: Example.Xyzzy a_acz) -> Example.foo @ a_acz (Example.$p1Xyzzy @ a_acz $dXyzzy_acA) 

    Please note that this may be specific to GHC. Tested with version 7.0.2.

+6
source

All Articles