2011-07-21 14 views
7

从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

这很有趣...我认为它可以。 – luqui

+0

为什么不试试呢? – fuz

回答

6

不,不需要包括所有的超类。如果你写

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

它会工作。但是,这里有两个可能的原因需要明确提及所有超类。

  1. 它可能更具有可读性,因为您可以一目了然地分辨出所有超类是什么。

  2. 这可能是稍微更有效,因为上市超明确将导致在运行时直接字典查找,而对于传递超它会首先寻找的字典超,然后查找在类成员那。

    例如,借此继承链:

    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。

+0

谢谢,这是有道理的。 – qubital

+3

将这些约束传播到子类是否值得编译器优化? – fuz

+3

@FUZxxl:我会这么认为的,是的。我可以看到唯一的缺点是字典会稍微大一点,但除非你有一个巨大的继承树,否则这不会成为一个问题。 – hammar

相关问题