Подтвердить что ты не робот

Является ли GHC автоматически производным экземпляром `Eq` действительно * O (N) *?

Я просто заметил, пытаясь научиться читать GHC Core, что автоматически созданный экземпляр Eq для типов данных типа enum, таких как

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

кажется, преобразуется в O (N) -подобный поиск при просмотре представления ядра GHC:

$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? Должны ли алгебраические типы данных предоставлять целочисленный идентификатор для каждого конструктора, который затем можно сравнивать непосредственно в O (1)? Кроме того, почему предложение первого случая для ETypeA не использует __DEFAULT, как это делают другие предложения?

обновление:

Согласно предложению Саймона Марлоу, я добавил 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 case и использованием dataToTag#, и почему это конкретное отсечение 9 конструкторов для использования dataToTag# реализовано в GHC.

4b9b3361

Ответ 1

Сравнение равенства EType является O (1), поскольку конструкция case - O (1).

Может существовать или не быть целым тегом для конструкторов. Существует несколько вариантов выбора уровня низкого уровня, поэтому созданный Core работает для всех из них. Тем не менее, вы всегда можете создать целочисленный тег для конструкторов и как я обычно реализую производное сравнение при написании компиляторов Haskell.

Я понятия не имею, почему ETypeA получает другое обращение. Похож на ошибку.