Я думаю, у вас есть ошибка в scan_partial_perms
,
scan_partial_perms ps v = map fromJust . takeWhile test $ scanl (>>=) (Just v) ps
scanl f s list
всегда начинается с s
, поэтому takeWhile test (scanl ...)
равно []
.Если это намеренно, это довольно запутано.Предполагая, что вы хотите
scan_partial_perms ps v = (v:) . map fromJust . takeWhile test . tail $ scanl (>>=) (Just v) ps
, вы мало что можете сделать.Вы можете {-# SPECIALISE #-}
сделать это так, словарь Eq
исключен для специализированных типов.Это пойдет вам на пользу, если компилятор не сделает этого сам по себе (а может, если увидит сайт использования).С ghc> = 7 вы можете вместо этого сделать его {-# INLINABLE #-}
, чтобы он мог быть специализированным и, возможно, встроенным на каждом сайте использования.
Я не знаю, что произойдет в будущем, но нана уровне ядра, map
, fromJust
и takeWhile
еще не встроены, поэтому, если вы достаточно отчаялись, вы можете получить, возможно, несколько десятых процента, вставив их вручную, если они не встроены позже вбэкэнд llvm:
scan_partial_perms ps v = v : go v ps
where
go w (q:qs) = case q w of
Just z
| z /= v -> z : go z qs
_ -> []
go _ _ = []
Но это очень дешевые функции, поэтому выгоды - если они вообще есть - были бы небольшими.
Так что то, что у вас уже есть, довольно хорошо, если ононедостаточно хорош, вам нужен другой путь атаки.
Тот, с индексированием списка,
perm l i = l !! (i `rem` length l)
-- parentheses necessary, I don't think (l !! i) `rem` length l was what you want
выглядит не очень хорошо.length
стоит дорого, (!!)
тоже дорого, поэтому в общем следует избегать обоих.