[Haskell-beginners] Re: Iterating through a list of char...
Daniel Fischer
daniel.is.fischer at web.de
Thu Apr 29 16:50:21 EDT 2010
Am Donnerstag 29 April 2010 21:37:15 schrieb Jean-Nicolas Jolivet:
> First I would like to thank everyone for the very interesting replies
> and suggestions I got so far!...
>
> I tried to implement (and at the very least understand) most of them!...
>
> To add to the context here, what I am trying to do is:
>
> -apply a "transformation" to a character (in my case, subtracting 42 to
> its ASCII value, which I obtain with chr(ord(c) - 42) -if the character
> is preceded by a specific character (that would be, an escape character,
> in this case '=') then subtract 106 to its value instead of 42... -if
> the character is the escape character itself, '=', then skip it
> altogether
Ah, that complicates matters a little.
- What happens if ord c < 42 (ord c < 106, if c is preceded by the escape
character?)
- What about escaped escape characters?
However,
foo xs = catMaybes $ zipWith f (' ':xs) xs
where
f _ '=' = Nothing
f '=' c = Just (chr $ ord c - 106)
f _ c = Just (chr $ ord c - 42)
is still pretty simple, as is the direct recursion
foo = go ' '
where
go _ ('=' :cs) = go '=' cs
go '=' (c:cs) = chr (ord c - 106) : go c cs
go _ (c:cs) = chr (ord c - 42) : go c cs
go _ _ = []
-- assuming that only characters > 'i' (chr 105) are escaped (or the escape
character itself, but that should be dropped regardless).
fooGen :: Char -> (Char -> Char) -> (Char -> Char) -> String -> String
fooGen e esc norm str = catMaybes $ zipWith f (d:str) str
where
d = if e == maxBound then pred e else succ e
f x y
| y == e = Nothing
| x == e = Just (esc y)
| otherwise = Just (norm y)
is an easy generalisation.
> (keeping in mind that the next character needs to be
> escaped)...
>
> I managed to do it, however I'm not totally satisfied in the way I did
> it... the problem was that... as I just explained, in some cases, the
> character that is being processed has to be "skipped" (and by that I
> mean, not added to the resulting string). This happens when the
> processed character IS the escape character...
>
> What I did was to build a List of Maybe Char.... my function does the
> proper operation on the character and returns a "Just Char" when the
> character is processed, or Nothing when it is the escaped character...
> so basically I would end up with something like: [Just 'f', Just 'o',
> Just 'o', Nothing]... I am mapping this using mapMaybe to end up with a
> proper String...
>
> Would there be any more efficient way of doing this?
That is already pretty efficient. The direct recursion is probably a bit
more efficient, but I don't think the difference will be large.
> Considering that
> the escape character should NOT be added to the resulting string, is
> there any way I can avoid using the Maybe monad?
Sure, apart from the direct recursion,
fooGen e esc norm str = tail $ foldr f [] (d:str)
where
d = if e == maxBound then pred e else succ e
f x (y:zs)
| y == e = x:zs
| x == e = x:esc y:zs
| otherwise = x:norm y:zs
f x [] = [x]
catMaybes and zipWith is clearer, though, and I don't think the foldr will
perform better.
>
> Once again, thanks everyone for all the suggestions!
>
> Jean-Nicolas Jolivet
More information about the Beginners
mailing list