replaceCount :: Int
             -> Regex
             -> Rope
             -> Rope
             -> Rope
replaceCount n r replacement haystack = replaceCount' n ("", haystack)
  where
    replaceCount' 0 (h1, h2) = R.append h1 h2
    replaceCount' n haystack@(h1, h2) =
        case matchOnce r h2 of
            Just match ->
                let (offset, len) = match ! 0
                    (prefix, result) = R.splitAt offset h2
                    h1' = R.concat [h1, prefix, replacement]
                    result' = R.drop len result
                in  replaceCount' (n - 1) (h1', result')
            Nothing -> replaceCount' 0 haystack
replaceCount :: Int
             -> Regex
             -> Rope
             -> Rope
             -> Rope
replaceCount n r replacement haystack = replaceCount' n ("", haystack)
  where
    replaceCount' 0 (h1, h2) = R.append h1 h2
    replaceCount' n haystack@(h1, h2) =
        case matchOnce r h2 of
            Just match ->
                let (offset, len) = match ! 0
                    (prefix, result) = R.splitAt offset h2
                    h1' = R.concat [h1, prefix, replacement]
                    result' = R.drop len result
                in  replaceCount' (n - 1) (h1', result')
            Nothing -> replaceCount' 0 haystack
replaceCount n r replacement haystack = replaceCount' n ("", haystack)
  where
    replaceCount' 0 (h1, h2) = R.append h1 h2
    replaceCount' n haystack@(h1, h2) =
        case matchOnce r h2 of
            Just match ->
                let (offset, len) = match ! 0
                    (prefix, result) = R.splitAt offset h2
                    h1' = R.concat [h1, prefix, replacement]
                    result' = R.drop len result
                in  replaceCount' (n - 1) (h1', result')
            Nothing -> replaceCount' 0 haystack