У меня есть код 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