[Haskell-cafe] Incrementation fails

Roel van Dijk vandijk.roel at gmail.com
Wed May 8 10:03:12 CEST 2013


> problem = replaceBasedIdx "X" ["b","d","f"] "aXcXeXgX"
> -- "abcdefg*** Exception: Prelude.(!!): index too large

This problem occurs because you never check if 'counter' is a valid
index in the 'replaceStrList'. You can solve it by not using the !!
operator at all. The solution is to also pass 'replaceStrList' in the
recursion. That way you can check whether you have exhausted all
strings in that list and as a bonus you do not need your counter
anymore:

> replaceBasedIdx :: String -> [String] -> String -> String
> replaceBasedIdx findStr replaceStrList myText = loop replaceStrList myText
>   where
>     loop :: [String] -> String -> String
>     loop rs [] = []
>     -- Check for empty list of replacements
>     loop [] text = text
>     -- Pattern match on the list of replacements to get both the
>     -- entire list rs, the first element r and the tail rs'.
>     loop rs@(r:rs') text =
>       let (prefix, rest) = splitAt n text
>       in if findStr == prefix
>          then r ++ loop rs' rest
>          else head text : loop rs (tail text)
>
>     n :: Int
>     n = length findStr



2013/5/8 Roel van Dijk <vandijk.roel at gmail.com>

> I stared at the code some more and deduced what I think is the
> intented meaning. Occurences of 'findStr' in 'myText' are replaced
> with the strings in 'replaceStrList'.
>
> So replaceBasedIdx "X" ["b","d","f"] "aXcXeXg" = "abcdefg"
>
> The reason your counter didn't increment is because it was defined as
> an argument to 'replaceBasedIdxSub'. That means its value is fixed
> once you evaluate that function. Its value will not change no matter
> how many times the inner 'loop' function is evaluated. The solution is
> to pass the counter as an argument to said 'loop' function. Now when
> 'loop' enters the recursion you can pass a different value, such as
> counter + 1.
>
> > replaceBasedIdx :: String -> [String] -> String -> String
> > replaceBasedIdx findStr replaceStrList myText = replaceBasedIdxSub
> findStr replaceStrList myText
>
> > replaceBasedIdxSub :: String -> [String] -> String -> String
> > replaceBasedIdxSub findStr replaceStrList myText = loop 0 myText
> >   where
> >     loop :: Int -> String -> String
> >     loop counter [] = []
> >     loop counter myText =
>  >       let (prefix, rest) = splitAt n myText
> >       in if findStr == prefix
> >          then (replaceStrList !! counter) ++ loop (counter + 1) rest
> >          else head myText : loop counter (tail myText)
> >
> >     n :: Int
> >     n = length findStr
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130508/14ab6b79/attachment-0001.htm>


More information about the Haskell-Cafe mailing list