Extract integers from a string that is split at given positions I am writing a program which runs quite slow and on profiling I found that the bottleneck is to split a given string at given positions.

The first and short version I wrote was (80% of 67 sec, i.e. 53 sec spent):

split list pos = uncurry (:) $ mapAccumR (flip splitAt) list pos


A faster version I wrote is (76% of 21 sec, i.e. 15 sec spent):

split :: String -&gt; [Int] -&gt; [Int]
split = go [] 0 0
    where
        -- no more string to split
        go nums num _ [] _ = num : nums
        -- no more position to split
        go nums num _ list [] = read (intToDigit num : list) : nums
        go nums num i (l:ls) pos@(p:ps)
            | i == p = go (num:nums) (digitToInt l) (i+1) ls ps
            | otherwise = go nums (10 * num + digitToInt l) (i+1) ls pos


How can I improve this?
Walking across the list of positions from the right cuts off suffixes, requiring you to keep traversing and copying the corresponding prefixes over. If you cut off prefixes instead, you only need to traverse once.

import Data.List
import Data.Tuple

splitAts :: [Int] -&gt; [a] -&gt; ([[a]], [a])
splitAts is xs = swap $ mapAccumL go xs (zipWith (-) is (0:is)) where
  go :: [a] -&gt; Int -&gt; ([a], [a])
  go xs i = swap $ splitAt i xs


This piece of code is, incidentally, the epitome of order confusion and what wouldn't happen if there was a way to bundle API updates with automatic patchers to old code.