ArrowList
hxt包中的类具有以下声明:
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
...?
不,没有必要包括所有的超类.如果你写
class (ArrowPlus a, ArrowApply a) => ArrowList a where
Run Code Online (Sandbox Code Playgroud)
它会工作.但是,以下是明确提及所有超类的两个可能原因.
它可能更具可读性,因为您可以一目了然地看出所有超类都是什么.
它可能稍微有点效率,因为显式列出超类将导致在运行时直接字典查找,而对于传递超类,它将首先查找超类的字典,然后在其中查找类成员.
例如,采用此继承链:
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
Run Code Online (Sandbox Code Playgroud)
查看为此生成的核心(with ghc -c -ddump-simpl
),我们看到这会生成一系列查找调用.它首先查找字典为Baz
in 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)))
Run Code Online (Sandbox Code Playgroud)
修改Xyzzy
明确提及的定义Foo
:
class (Foo a, Baz a) => Xyzzy a
Run Code Online (Sandbox Code Playgroud)
我们看到它现在可以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)
Run Code Online (Sandbox Code Playgroud)
请注意,这可能是GHC特定的.测试版本7.0.2.