hxt包中的ArrowList
类具有以下声明:
class (Arrow a, ArrowPlus a, ArrowZero a, ArrowApply a) => ArrowList a where
...
ArrowPlus
类声明为:
class ArrowZero a => ArrowPlus a where
...
ArrowZero
类声明为:
class Arrow a => ArrowZero a where
...
ArrowApply
类声明为:
class Arrow a => ArrowApply a where
...
为什么不能把它写成:
class (ArrowPlus a, ArrowApply a) => ArrowList a where
......?
答案 0 :(得分:6)
不,没有必要包括所有超类。如果你写
class (ArrowPlus a, ArrowApply a) => ArrowList a where
它会起作用。但是,以下是明确提及所有超类的两个可能原因。
它可能更具可读性,因为您可以一目了然地了解所有超类的内容。
它可能稍微更有效,因为显式列出超类将导致在运行时直接字典查找,而对于传递超类,它将首先查找超类的字典和然后在那里查找类成员。
例如,请使用此继承链:
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
查看为此生成的核心(使用ghc -c -ddump-simpl
),我们看到这会生成一系列查找调用。它首先在Baz
中查找Xyzzy
字典,然后在其中查找Bar
字典,然后查找Foo
,最后查找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)))
修改Xyzzy
的定义以明确提及Foo
:
class (Foo a, Baz a) => Xyzzy a
我们发现现在可以直接从Foo
获取Xyzzy
词典并在其中查找foo
。
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)
请注意,这可能是针对GHC的。使用版本7.0.2进行测试。