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

Удаление "case" с повторяющимися ветвями из Haskell Core

У меня есть код Haskell, который выглядит так:

fst . f $ (Z :. i `div` 2)

Z и :. берутся из Repa библиотеки и определяются следующим образом:

data Z = Z deriving (Show, Read, Eq, Ord)
infixl 3 :. 
data tail :. head = !tail :. !head deriving (Show, Read, Eq, Ord)

Правило выражения $ определяет индекс массива, а f - это функция, которая принимает этот индекс и возвращает пару. Это скомпилируется следующим Core:

case f_a2pC
       (case ># x_s32E 0 of _ {
          False ->
            case <# x_s32E 0 of _ {
              False -> :. Z (I# (quotInt# x_s32E 2));
              True -> :. Z (I# (-# (quotInt# (+# x_s32E 1) 2) 1))
            };
          True ->
            case <# x_s32E 0 of _ {
              False -> :. Z (I# (quotInt# x_s32E 2));
              True -> :. Z (I# (-# (quotInt# (+# x_s32E 1) 2) 1))
            }
        })
of _ { (x1_a2Cv, _) ->
x1_a2Cv
}

Мне кажется очевидным (возможно, неверно), что оператор среднего случая (тот, у которого ># x_s32E 0 как scrutinee) избыточен, так как обе ветки идентичны. Есть ли что-нибудь, что я могу сделать, чтобы избавиться от него? Я компилирую свой код с использованием параметров GHC, рекомендованных в документации Repa: -O2 -Odph -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000

4b9b3361

Ответ 1

Действительно, две ветки case ># x_s32E 0 of идентичны, и, следовательно, case является избыточным. Кажется, что выравнивание case для идентичных ветвей не выполняется после того, как обе ветки стали идентичными - вероятно, стоит отчет об ошибке. Этот вопрос может быть уместным, но поскольку ядро, созданное для отрицательных делителей, хорошо, я подал новая ошибка.

Использование более простого quot - if i не может быть законно отрицательным, - которое непосредственно сопоставляется с оператором машинного деления, делает код более простым, так что для этого не нужно генерировать никаких ветвей.