派生`Eq`实例真* O(N)*?

我只是在尝试学习阅读GHC Core时注意到,自动派生的枚举类型数据类型的Eq实例如

data EType = ETypeA | ETypeB | ETypeC | ETypeD
           | ETypeE | ETypeF | ETypeG | ETypeH
           deriving (Eq)

在查看GHC的核心代表时,似乎转变为O(N)式的查询:

$fEqEType_$c== =
   (a_ahZ :: EType) (b_ai0 :: EType) ->
    case a_ahZ of _ {
      ETypeA ->
        case b_ai0 of _ {
          ETypeA -> True;
          ETypeB -> False;
          ETypeC -> False;
          ETypeD -> False;
          ETypeE -> False;
          ETypeF -> False;
          ETypeG -> False;
          ETypeH -> False
        };
      ETypeB -> case b_ai0 of _ {__DEFAULT -> False; ETypeB -> True};
      ETypeC -> case b_ai0 of _ {__DEFAULT -> False; ETypeC -> True};
      ETypeD -> case b_ai0 of _ {__DEFAULT -> False; ETypeD -> True};
      ETypeE -> case b_ai0 of _ {__DEFAULT -> False; ETypeE -> True};
      ETypeF -> case b_ai0 of _ {__DEFAULT -> False; ETypeF -> True};
      ETypeG -> case b_ai0 of _ {__DEFAULT -> False; ETypeG -> True};
      ETypeH -> case b_ai0 of _ {__DEFAULT -> False; ETypeH -> True}
    }

我误解了GHC核心输出? 代数数据类型不应该为每个构造函数提供一个整数ID,然后可以直接在O(1)中进行比较? 另外,为什么ETypeA的第一个case子句ETypeA其他子句那样使用__DEFAULT呢?

更新:

根据Simon Marlow的建议,我添加了第9个构造函数ETypeI ,然后GHC切换到使用dataToOtag#

$fEqEType_$c/= =
   (a_ahS :: EType) (b_ahT :: EType) ->
    case dataToTag# @ EType a_ahS of a#_ahQ {
      __DEFAULT ->
        case dataToTag# @ EType b_ahT of b#_ahR {
          __DEFAULT ->
            case ==# a#_ahQ b#_ahR of _ {
              False -> True; True -> False
            }
        }
    }

对我而言,这增加了GHC核心的casedataToTag#使用之间的权衡问题,以及为什么在GHC中实现使用dataToTag#的9个构造函数的特定截止。


EType平等比较是O(1),因为case结构是O(1)。

构造函数可能有或没有整型标记。 有几种低级代表选择,所以核心产生了所有这些作品。 也就是说,您总是可以为构造函数创建一个整型标记,这就是我在编写Haskell编译器时通常实现派生的比较。

我不知道为什么ETypeA得到不同的治疗。 看起来像bug。

链接地址: http://www.djcxy.com/p/43063.html

上一篇: derived `Eq` instance really *O(N)*?

下一篇: Can a Haskell type constructor have non