是否有必要在类声明的类上下文中指定每个超类?

qub*_*tal 7 haskell

ArrowListhxt包中的类具有以下声明:

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...?

ham*_*mar 6

不,没有必要包括所有的超类.如果你写

class (ArrowPlus a, ArrowApply a) => ArrowList a where
Run Code Online (Sandbox Code Playgroud)

它会工作.但是,以下是明确提及所有超类的两个可能原因.

  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
    
    Run Code Online (Sandbox Code Playgroud)

    查看为此生成的核心(with ghc -c -ddump-simpl),我们看到这会生成一系列查找调用.它首先查找字典为Bazin 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.

  • 编译器优化是否值得将这些约束传播到子类? (3认同)
  • @FUZxxl:我想是的,是的.我能看到的唯一缺点是字典会稍微大一点,但除非你有一个巨大的继承树,否则这不会成为一个问题. (3认同)