Насчёт борьбы со .slice() в uncons есть одна идея. Так как массивы всегда иммутабельные, можно создать обёртку, которая указывает на диапазон индексов в Array, и использовать её так, как будто это настоящий Array.
type Start = Int
type End = Int
data FastArray a = Literally (Array a) | View Start End (Array a)
derive instance genericFastArray :: Generic (FastArray a) _
instance showFastArray :: Show a => Show (FastArray a) where
show = genericShow
uncns :: forall a. FastArray a -> Maybe { head:: a, tail :: FastArray a }
uncns (Literally arr) =
map (\head -> { head, tail: View 1 (length arr) arr}) (head arr)
uncns (View start end arr)
| start < end =
map (\head -> { head, tail: View (start + 1) end arr }) (arr !! start)
| otherwise = Nothing
Возможно, что это уже сделано кем-то, не проверял.