The ArrowList
class from the hxt package has the following declaration:
class (Arrow a, ArrowPlus a, ArrowZero a, ArrowApply a) => ArrowList a where
...
The ArrowPlus
class is declared as:
class ArrowZero a => ArrowPlus a where
...
The ArrowZero
class is declared as:
class Arrow a => ArrowZero a where
...
And the ArrowApply
class is declared as:
class Arrow a => ArrowApply a where
...
Why can't it just be written as:
class (ArrowPlus a, ArrowApply a) => ArrowList a where
...?
No, it's not necessary to include all the superclasses. If you write
class (ArrowPlus a, ArrowApply a) => ArrowList a where
it will work. However, here are two possible reasons for mentioning all the superclasses explicitly.
It might be more readable as you can tell at a glance what all the superclasses are.
It might be slightly more efficient, as listing the superclasses explicitly will result in a direct dictionary lookup at runtime, while for a transitive superclass it will first lookup the dictionary for the superclass and then lookup 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 core for this (with ghc -c -ddump-simpl
), we see that this generates a chain of lookup calls. It first looks up the dictionary for Baz
in Xyzzy
, then Bar
in that, then Foo
, and finally it can look up 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)))
Modifying the definition of Xyzzy
to explicitly mention Foo
:
class (Foo a, Baz a) => Xyzzy a
We see that it can now get the Foo
dictionary straight from the Xyzzy
one and look up foo
in that.
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)
Note that this may be GHC-specific. Tested with version 7.0.2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With