Iterating through a list of char...

Hi there! I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do! I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is: while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i] I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated! Jean-Nicolas Jolivet

On Wed, 2010-04-28 at 10:56 -0400, Jean-Nicolas Jolivet wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length:
I assume i > 0 as otherwise my_string[i-1] is illegal
if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet
Very simple version: func (x:xs) = x:helper x xs func [] = [] helper p (x:xs) | p == some_char = x':helper x' xs | otherwise = x'':helper x'' xs where x' = doSomething x x'' = doSomethingElse x helper p [] = [] or (for helper): helper p (x:xs) = let x' | p == some_char = doSomething x | otherwise = doSomethingElse x in x':helper x' xs helper p [] = [] Advanced version (depends on state of character before change) func s@(x:xs) = x:zipWith proc s xs where proc (p, x) | p == some_char = doSomething x | otherwise = soSomethingElse x Advanced version: func (x:xs) = let s = x:zipWith proc s xs proc (p, x) | p == some_char = doSomething x | otherwise = soSomethingElse x in s It can be also expressed using folds. Choose version which suits you best. Regards

Thanks a lot! I love the fact that you included different versions! Will definitely look into each versions and try to understand them all! Jean-Nicolas On 2010-04-28, at 11:16 AM, Maciej Piechotka wrote:
On Wed, 2010-04-28 at 10:56 -0400, Jean-Nicolas Jolivet wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length:
I assume i > 0 as otherwise my_string[i-1] is illegal
if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet
Very simple version:
func (x:xs) = x:helper x xs func [] = []
helper p (x:xs) | p == some_char = x':helper x' xs | otherwise = x'':helper x'' xs where x' = doSomething x x'' = doSomethingElse x helper p [] = []
or (for helper):
helper p (x:xs) = let x' | p == some_char = doSomething x | otherwise = doSomethingElse x in x':helper x' xs helper p [] = []
Advanced version (depends on state of character before change)
func s@(x:xs) = x:zipWith proc s xs where proc (p, x) | p == some_char = doSomething x | otherwise = soSomethingElse x
Advanced version:
func (x:xs) = let s = x:zipWith proc s xs proc (p, x) | p == some_char = doSomething x | otherwise = soSomethingElse x in s
It can be also expressed using folds. Choose version which suits you best.
Regards _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Hello, I would do: doSmthg a = if a == 'a' then (const 'A') else id trans c = zipWith doSmthg (" " ++ c) c
trans "arga" "aAga"
The idea is to zip the string with the same string with an offset of character.
I thing my solution could be cleaner by using Maybe monad to handle
the first character's problem.
Corentin
On 4/28/10, Maciej Piechotka
On Wed, 2010-04-28 at 10:56 -0400, Jean-Nicolas Jolivet wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length:
I assume i > 0 as otherwise my_string[i-1] is illegal
if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet
Very simple version:
func (x:xs) = x:helper x xs func [] = []
helper p (x:xs) | p == some_char = x':helper x' xs | otherwise = x'':helper x'' xs where x' = doSomething x x'' = doSomethingElse x helper p [] = []
or (for helper):
helper p (x:xs) = let x' | p == some_char = doSomething x | otherwise = doSomethingElse x in x':helper x' xs helper p [] = []
Advanced version (depends on state of character before change)
func s@(x:xs) = x:zipWith proc s xs where proc (p, x) | p == some_char = doSomething x | otherwise = soSomethingElse x
Advanced version:
func (x:xs) = let s = x:zipWith proc s xs proc (p, x) | p == some_char = doSomething x | otherwise = soSomethingElse x in s
It can be also expressed using folds. Choose version which suits you best.
Regards

Hi!
Since the function to apply depends on the current element, and the previous
element, you need to define what to do if an element doesn't have a
previous, namely the first element in the list. I guess then it'll be quite
easy to implement such a function using explicit recursion.
The function to apply at each step is of type :: a -> a -> a (take the
previous element, and this element, and generate an element to replace the
current element, right?)
The list is of type [a], and the result will be of type [a] again.
foo :: (a -> a -> a) -> [a] -> [a]
foo f (x:y:rest) = f x y : foo f (y:rest)
foo f _ = []
This function is ready-to-use, except a case to handle the first element. It
would simply delete the first element.
*> foo (+) [1,2,3]
[3,5]
You can of course have a function like callfoo, which will prepend the first
element untouched.
callfoo :: (a -> a -> a) -> [a] -> [a]
callfoo f (x:xs) = x : foo f (x:xs)
I would generalise on this a little bit more, and introduce a function to
handle the first element differently.
bar :: (a -> b) -> (a -> a -> b) -> [a] -> [b]
bar f g (x:xs) = f x : loop g (x:xs)
where loop t (i:j:rest) = t i j : loop t (j:rest)
loop _ _ = []
bar _ _ _ = []
I think, the best thing about this version is that it doesn't limit the
input and the output of the function to be of the same type! (Figuring out
the meaning of a's and b's is left to the reader)
Note that the loop function defined within bar is almost the same with foo
defined before.
to test:
*> bar id (+) [1,2,3]
[1,3,5]
Hope this will be helpful, and not confusing. If you feel confused, just
think about the types one more time :)
Best,
On 28 April 2010 15:56, Jean-Nicolas Jolivet
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun

Ozgur Akgun wrote:
*> bar id (+) [1,2,3] [1,3,5]
Incidentally, scanl1 (+) [1,2,3] == [1,3,5], i.e. scanl1 = bar id.
/Jonas
On 28 April 2010 17:40, Ozgur Akgun
Hi!
Since the function to apply depends on the current element, and the previous element, you need to define what to do if an element doesn't have a previous, namely the first element in the list. I guess then it'll be quite easy to implement such a function using explicit recursion.
The function to apply at each step is of type :: a -> a -> a (take the previous element, and this element, and generate an element to replace the current element, right?) The list is of type [a], and the result will be of type [a] again.
foo :: (a -> a -> a) -> [a] -> [a] foo f (x:y:rest) = f x y : foo f (y:rest) foo f _ = []
This function is ready-to-use, except a case to handle the first element. It would simply delete the first element.
*> foo (+) [1,2,3] [3,5]
You can of course have a function like callfoo, which will prepend the first element untouched.
callfoo :: (a -> a -> a) -> [a] -> [a] callfoo f (x:xs) = x : foo f (x:xs)
I would generalise on this a little bit more, and introduce a function to handle the first element differently.
bar :: (a -> b) -> (a -> a -> b) -> [a] -> [b] bar f g (x:xs) = f x : loop g (x:xs) where loop t (i:j:rest) = t i j : loop t (j:rest) loop _ _ = [] bar _ _ _ = []
I think, the best thing about this version is that it doesn't limit the input and the output of the function to be of the same type! (Figuring out the meaning of a's and b's is left to the reader) Note that the loop function defined within bar is almost the same with foo defined before.
to test:
*> bar id (+) [1,2,3] [1,3,5]
Hope this will be helpful, and not confusing. If you feel confused, just think about the types one more time :)
Best,
On 28 April 2010 15:56, Jean-Nicolas Jolivet
wrote: Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Hello,
i have scanl1 (+) [1,2,3] == [1,3,6]
since scanl apply successive reducing.
am i missing something?
On 4/28/10, Jonas Almström Duregård
Ozgur Akgun wrote:
*> bar id (+) [1,2,3] [1,3,5]
Incidentally, scanl1 (+) [1,2,3] == [1,3,5], i.e. scanl1 = bar id.
/Jonas
On 28 April 2010 17:40, Ozgur Akgun
wrote: Hi!
Since the function to apply depends on the current element, and the previous element, you need to define what to do if an element doesn't have a previous, namely the first element in the list. I guess then it'll be quite easy to implement such a function using explicit recursion.
The function to apply at each step is of type :: a -> a -> a (take the previous element, and this element, and generate an element to replace the current element, right?) The list is of type [a], and the result will be of type [a] again.
foo :: (a -> a -> a) -> [a] -> [a] foo f (x:y:rest) = f x y : foo f (y:rest) foo f _ = []
This function is ready-to-use, except a case to handle the first element. It would simply delete the first element.
*> foo (+) [1,2,3] [3,5]
You can of course have a function like callfoo, which will prepend the first element untouched.
callfoo :: (a -> a -> a) -> [a] -> [a] callfoo f (x:xs) = x : foo f (x:xs)
I would generalise on this a little bit more, and introduce a function to handle the first element differently.
bar :: (a -> b) -> (a -> a -> b) -> [a] -> [b] bar f g (x:xs) = f x : loop g (x:xs) where loop t (i:j:rest) = t i j : loop t (j:rest) loop _ _ = [] bar _ _ _ = []
I think, the best thing about this version is that it doesn't limit the input and the output of the function to be of the same type! (Figuring out the meaning of a's and b's is left to the reader) Note that the loop function defined within bar is almost the same with foo defined before.
to test:
*> bar id (+) [1,2,3] [1,3,5]
Hope this will be helpful, and not confusing. If you feel confused, just think about the types one more time :)
Best,
On 28 April 2010 15:56, Jean-Nicolas Jolivet
wrote: Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Exactly:
*> bar id (+) [1..5]
[1,3,5,7,9]
*> scanl1 (+) [1..5]
[1,3,6,10,15]
But they are close enough, I guess :)
2010/4/28 Dupont Corentin
Hello, i have scanl1 (+) [1,2,3] == [1,3,6] since scanl apply successive reducing. am i missing something?
Ozgur Akgun wrote:
*> bar id (+) [1,2,3] [1,3,5]
Incidentally, scanl1 (+) [1,2,3] == [1,3,5], i.e. scanl1 = bar id.
/Jonas
On 28 April 2010 17:40, Ozgur Akgun
wrote: Hi!
Since the function to apply depends on the current element, and the previous element, you need to define what to do if an element doesn't have a previous, namely the first element in the list. I guess then it'll be quite easy to implement such a function using explicit recursion.
The function to apply at each step is of type :: a -> a -> a (take the previous element, and this element, and generate an element to replace
On 4/28/10, Jonas Almström Duregård
wrote: the current element, right?) The list is of type [a], and the result will be of type [a] again.
foo :: (a -> a -> a) -> [a] -> [a] foo f (x:y:rest) = f x y : foo f (y:rest) foo f _ = []
This function is ready-to-use, except a case to handle the first element. It would simply delete the first element.
*> foo (+) [1,2,3] [3,5]
You can of course have a function like callfoo, which will prepend the first element untouched.
callfoo :: (a -> a -> a) -> [a] -> [a] callfoo f (x:xs) = x : foo f (x:xs)
I would generalise on this a little bit more, and introduce a function to handle the first element differently.
bar :: (a -> b) -> (a -> a -> b) -> [a] -> [b] bar f g (x:xs) = f x : loop g (x:xs) where loop t (i:j:rest) = t i j : loop t (j:rest) loop _ _ = [] bar _ _ _ = []
I think, the best thing about this version is that it doesn't limit the input and the output of the function to be of the same type! (Figuring out the meaning of a's and b's is left to the reader) Note that the loop function defined within bar is almost the same with foo defined before.
to test:
*> bar id (+) [1,2,3] [1,3,5]
Hope this will be helpful, and not confusing. If you feel confused, just think about the types one more time :)
Best,
On 28 April 2010 15:56, Jean-Nicolas Jolivet < jeannicolascocoa@gmail.com> wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun

5 or 6, does it really matter? ;)
Sorry about the confusion...
/J
2010/4/28 Dupont Corentin
Hello, i have scanl1 (+) [1,2,3] == [1,3,6] since scanl apply successive reducing. am i missing something?
On 4/28/10, Jonas Almström Duregård
wrote: Ozgur Akgun wrote:
*> bar id (+) [1,2,3] [1,3,5]
Incidentally, scanl1 (+) [1,2,3] == [1,3,5], i.e. scanl1 = bar id.
/Jonas
On 28 April 2010 17:40, Ozgur Akgun
wrote: Hi!
Since the function to apply depends on the current element, and the previous element, you need to define what to do if an element doesn't have a previous, namely the first element in the list. I guess then it'll be quite easy to implement such a function using explicit recursion.
The function to apply at each step is of type :: a -> a -> a (take the previous element, and this element, and generate an element to replace the current element, right?) The list is of type [a], and the result will be of type [a] again.
foo :: (a -> a -> a) -> [a] -> [a] foo f (x:y:rest) = f x y : foo f (y:rest) foo f _ = []
This function is ready-to-use, except a case to handle the first element. It would simply delete the first element.
*> foo (+) [1,2,3] [3,5]
You can of course have a function like callfoo, which will prepend the first element untouched.
callfoo :: (a -> a -> a) -> [a] -> [a] callfoo f (x:xs) = x : foo f (x:xs)
I would generalise on this a little bit more, and introduce a function to handle the first element differently.
bar :: (a -> b) -> (a -> a -> b) -> [a] -> [b] bar f g (x:xs) = f x : loop g (x:xs) where loop t (i:j:rest) = t i j : loop t (j:rest) loop _ _ = [] bar _ _ _ = []
I think, the best thing about this version is that it doesn't limit the input and the output of the function to be of the same type! (Figuring out the meaning of a's and b's is left to the reader) Note that the loop function defined within bar is almost the same with foo defined before.
to test:
*> bar id (+) [1,2,3] [1,3,5]
Hope this will be helpful, and not confusing. If you feel confused, just think about the types one more time :)
Best,
On 28 April 2010 15:56, Jean-Nicolas Jolivet
wrote: Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Hey!
Keep passing the current char to your next call of the function (your next "iteration" as you said), that way you have the previos char in the current "iteration" and you can use it. The first time you call it make sure you call it with a dummy char that you know it will do what supposed to.
Greetings,
Hector Guilarte
Enviado desde mi dispositivo movil BlackBerry® de Digitel.
-----Original Message-----
From: 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 (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? Considering that the escape character should NOT be added to the resulting string, is there any way I can avoid using the Maybe monad? Once again, thanks everyone for all the suggestions! Jean-Nicolas Jolivet On 2010-04-28, at 10:56 AM, Jean-Nicolas Jolivet wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet

I won't attempt writing a general-case function now. If I understood your
(rather long) description correctly, you want to
- subtract 42 from the ascii value of the char, except when it is preceeded
by '=', in which case you subtract 106 instead.
foo :: [Char] -> [Char]
foo ('=':x:xs) = chr (ord x - 106) : foo xs
foo (x:xs) = chr (ord x - 42) : foo xs
foo _ = []
Hope I understood the problem correctly.
Best,
On 29 April 2010 20:37, 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 (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? Considering that the escape character should NOT be added to the resulting string, is there any way I can avoid using the Maybe monad?
Once again, thanks everyone for all the suggestions!
Jean-Nicolas Jolivet
On 2010-04-28, at 10:56 AM, Jean-Nicolas Jolivet wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun

This works, except for the case where '=' appears more than twice
consecutively. A string of multiple '=' should be treated as a single '='.
On Thu, Apr 29, 2010 at 16:26, Ozgur Akgun
I won't attempt writing a general-case function now. If I understood your (rather long) description correctly, you want to - subtract 42 from the ascii value of the char, except when it is preceeded by '=', in which case you subtract 106 instead.
foo :: [Char] -> [Char] foo ('=':x:xs) = chr (ord x - 106) : foo xs foo (x:xs) = chr (ord x - 42) : foo xs foo _ = []
Hope I understood the problem correctly. Best,
On 29 April 2010 20:37, Jean-Nicolas Jolivet
wrote: 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 (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? Considering that the escape character should NOT be added to the resulting string, is there any way I can avoid using the Maybe monad?
Once again, thanks everyone for all the suggestions!
Jean-Nicolas Jolivet
On 2010-04-28, at 10:56 AM, Jean-Nicolas Jolivet wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- mac

ok then,
foo ('=':'=':x:xs) = foo ('=':x:xs)
foo ('=':x:xs) = chr (ord x - 106) : foo xs
foo (x:xs) = chr (ord x - 42) : foo xs
foo _ = []
On 29 April 2010 21:31, matthew coolbeth
This works, except for the case where '=' appears more than twice consecutively. A string of multiple '=' should be treated as a single '='.
On Thu, Apr 29, 2010 at 16:26, Ozgur Akgun
wrote: I won't attempt writing a general-case function now. If I understood your (rather long) description correctly, you want to - subtract 42 from the ascii value of the char, except when it is preceeded by '=', in which case you subtract 106 instead.
foo :: [Char] -> [Char] foo ('=':x:xs) = chr (ord x - 106) : foo xs foo (x:xs) = chr (ord x - 42) : foo xs foo _ = []
Hope I understood the problem correctly. Best,
On 29 April 2010 20:37, Jean-Nicolas Jolivet
wrote: 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 (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? Considering that the escape character should NOT be added to the resulting string, is there any way I can avoid using the Maybe monad?
Once again, thanks everyone for all the suggestions!
Jean-Nicolas Jolivet
On 2010-04-28, at 10:56 AM, Jean-Nicolas Jolivet wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- mac
-- Ozgur Akgun

Haha, sorry for the (rather long) description ;) The ending was really the important part :) Basically I just wanted to explain the context of what I'm trying to do. Like I said, I already figured out a way to do all that... I'm just wondering if there is a better way to get to the final string result than building a list of Maybe Char and mapping it using mapMaybe...(considering that some characters of the initial string will NOT end up in the resulting string)... Every solution I found was iterating to a list of character one character at a time, and outputting a character as a result (whether it is by recursion, mapping, etc..), however, what I was trying to explain in my previous post was that; when I am processing the escape character, this character should not be added to the resulting string... This is where I decided to use the Maybe monad..I'm just wondering if there is a better way...! Jean-Nicolas Jolivet On 2010-04-29, at 4:26 PM, Ozgur Akgun wrote:
I won't attempt writing a general-case function now. If I understood your (rather long) description correctly, you want to - subtract 42 from the ascii value of the char, except when it is preceeded by '=', in which case you subtract 106 instead.
foo :: [Char] -> [Char] foo ('=':x:xs) = chr (ord x - 106) : foo xs foo (x:xs) = chr (ord x - 42) : foo xs foo _ = []
Hope I understood the problem correctly. Best,
On 29 April 2010 20:37, Jean-Nicolas Jolivet
wrote: 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 (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? Considering that the escape character should NOT be added to the resulting string, is there any way I can avoid using the Maybe monad?
Once again, thanks everyone for all the suggestions!
Jean-Nicolas Jolivet
On 2010-04-28, at 10:56 AM, Jean-Nicolas Jolivet wrote:
Hi there!
I'm trying to iterate through each character of a string (that part I can do!) however, I need to apply a transformation to each character...based on the previous character in the string! This is the part I have no clue how to do!
I'm totally new to Haskell so I'm pretty sure I'm missing something obvious... I tried with list comprehensions...map... etc... but I can't figure out how I can access the previous character in my string in each "iteration".... to use simple pseudo code, what i need to do is:
while i < my_string length: if my_string[i-1] == some_char: do something with my_string[i] else do something else with my_string[i]
I'm using imperative programming here obviously since it's what I am familiar with...but any help as to how I could "translate" this to functional programming would be really appreciated!
Jean-Nicolas Jolivet
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun

On 29 April 2010 21:39, Jean-Nicolas Jolivet
Every solution I found was iterating to a list of character one character at a time, and outputting a character as a result (whether it is by recursion, mapping, etc..), however, what I was trying to explain in my previous post was that; when I am processing the escape character, this character should not be added to the resulting string... This is where I decided to use the Maybe monad..I'm just wondering if there is a better way...!
Hi Jean-Nicolas The 'hand crafted lexer' style is quite common for this, with different functions for different states (here body and escape). I use a Hughes list as an explicit accumulator (a Hughes list is sometimes called a difference list and familiar for strings as the ShowS type synonym). This has more efficient right-addition (snoc) than normal lists [a].
toString :: ShowS -> String toString = ($ [])
snoc :: ShowS -> Char -> ShowS snoc f a = f . (a:)
emptyH :: ShowS emptyH = id
escape :: String -> ShowS -> ShowS escape (_:xs) acc = body xs acc -- drop1, change state escape _ acc = acc -- oh dear escape to the end-of-string
body :: String -> ShowS -> ShowS body ('\\':xs) acc = escape xs acc -- change state body (x:xs) acc = body xs (acc `snoc` x) body _ acc = acc
run :: String -> String run xs = toString (body xs emptyH)
demo1 = run "\\s1234" -- "1234"
Best wishes Stephen

Am Donnerstag 29 April 2010 22:39:05 schrieb Jean-Nicolas Jolivet:
Every solution I found was iterating to a list of character one character at a time, and outputting a character as a result (whether it is by recursion, mapping, etc..),
Well, that's necessary for what you want to do, isn't it?
however, what I was trying to explain in my previous post was that; when I am processing the escape character, this character should not be added to the resulting string... This is where I decided to use the Maybe monad..I'm just wondering if there is a better way...!
Depends on your criteria. For raw performance, I think the directly coded recursion is a bit better (btw, fooGen e esc norm = go False where go b (x:xs) | x == e = go True xs | b = esc x : go False xs | otherwise = norm x : go False xs go _ [] = [] ). For code cleanliness, catMaybes&zipWith and a good directly coded recursion are about equal. For leetness, the foldr is beats them, but surely one could do much 'better'.

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

-- assuming that only characters > 'i' (chr 105) are escaped (or the escape character itself, but that should be dropped regardless).
Sorry, this is my fault for not being clearer about it: I am decoding text that is already encoded with a Binary to ASCII encoding... the exact encoding process is this: 1. Fetch a character from the input stream. 2. Increment the character's ASCII value by 42, modulo 256 3. If the result is a critical character ('\NUL', '\r', '\n' or '='), write the escape character ('=') to the output stream and increment character's ASCII value by 64, modulo 256. 4. Output the character to the output stream. I am writing a decoder here so obviously I am reversing the process.... (I remove 42 for regular characters, 106 for special characters...and if the result is < 0, I add 256 to it...) Just adding (yet again) more context information here ;) Still trying to fully understand your last suggestions Daniel! :) Thanks again! Also, I wouldn't want anyone to think I just want someone to write the algorithm for me! :) Like I said, I already have a fully working algorithm, but being new to Haskell, I'm looking for ways to optimize it (or, really just different ways that I could do it!) Here's how I am doing it right now (I am using ByteString here, but it should be pretty straightforward anyway)... I'm warning you, this is pretty ugly :) -- Decode an encoded ByteString -- the zip + tail method removes the first character so I am adding it afterward (ugly) decodeByteString :: L.ByteString -> L.ByteString decodeByteString str = do let str1 = mapMaybe decodepair (L.zip str(L.tail str)) let firstChar = decodechar (ord(L.head str) - 42) L.pack (firstChar:str1) -- Decode a pair of character, returning either the -- decoded character or Nothing decodepair :: (Char, Char) -> Maybe Char decodepair cs | snd(cs) == '=' = Nothing | fst(cs) == '=' = Just (decodechar(ord(snd cs) - 106)) | otherwise = Just (decodechar(ord(snd cs) - 42)) -- Reverse the modulo 256... decodechar :: Int -> Char decodechar i | i < 0 = chr (i + 256) | otherwise = chr i Jean-Nicolas Jolivet On 2010-04-29, at 4:50 PM, Daniel Fischer wrote:
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

Am Donnerstag 29 April 2010 23:13:21 schrieb Jean-Nicolas Jolivet:
-- assuming that only characters > 'i' (chr 105) are escaped (or the escape character itself, but that should be dropped regardless).
Sorry, this is my fault for not being clearer about it: I am decoding text that is already encoded with a Binary to ASCII encoding... the exact encoding process is this:
1. Fetch a character from the input stream. 2. Increment the character's ASCII value by 42, modulo 256 3. If the result is a critical character ('\NUL', '\r', '\n' or '='), write the escape character ('=') to the output stream and increment character's ASCII value by 64, modulo 256. 4. Output the character to the output stream.
Okay, so there are no two escape characters in succession.
I am writing a decoder here so obviously I am reversing the process.... (I remove 42 for regular characters, 106 for special characters...and if the result is < 0, I add 256 to it...)
Just adding (yet again) more context information here ;) Still trying to fully understand your last suggestions Daniel! :) Thanks again!
Also, I wouldn't want anyone to think I just want someone to write the algorithm for me! :) Like I said, I already have a fully working algorithm, but being new to Haskell, I'm looking for ways to optimize it (or, really just different ways that I could do it!)
Here's how I am doing it right now (I am using ByteString here,
Then the foldr is not the best option.
but it should be pretty straightforward anyway)... I'm warning you, this is pretty ugly :)
-- Decode an encoded ByteString -- the zip + tail method removes the first character so I am adding it afterward (ugly) decodeByteString :: L.ByteString -> L.ByteString decodeByteString str = do let str1 = mapMaybe decodepair (L.zip str(L.tail str)) let firstChar = decodechar (ord(L.head str) - 42) L.pack (firstChar:str1)
Is it really necessary to pack it? That's a relatively expensive operation, it may be better to have it return a String if you're not doing anything with it after decoding except writing it to a file or so. The zipping is also not the optimal choice, it takes a lot of checking for the chunk-boundaries (I assume you're using lazy ByteStrings, since you chose the prefix L), and you construct pairs only to deconstruct them immediately (the compiler *may* optimise them away, but I'm skeptical).
-- Decode a pair of character, returning either the -- decoded character or Nothing decodepair :: (Char, Char) -> Maybe Char decodepair cs
| snd(cs) == '=' = Nothing | fst(cs) == '=' = Just (decodechar(ord(snd cs) - 106)) | otherwise = Just (decodechar(ord(snd cs) - 42))
-- Reverse the modulo 256... decodechar :: Int -> Char decodechar i
| i < 0 = chr (i + 256) | otherwise = chr i
Since you're doing arithmetic modulo 256, that stuff can be done faster and simpler with Word8. ---------------------------------------------------------------------- {-# LANGUAGE BangPatterns #-} import qualified Data.ByteString.Lazy as L import qualified Data.ByteString as S import Data.ByteString.Unsafe (unsafeAt) escape :: Word8 -> Word8 escape = (+150) normal :: Word8 -> Word8 normal = (+214) decodeW :: L.ByteString -> [Word8] decodeW = dec False . L.toChunks where dec _ [] = [] dec esc (str:more) = go esc 0 where !len = S.length str {-# INLINE charAt #-} charAt :: Int -> Word8 charAt i = unsafeAt str i go !b !i | i == len = dec b more | b = escape (charAt i) : go False (i+1) | otherwise = case charAt i of 61 -> go True (i+1) c -> normal c : go False (i+1) word8ToChar :: Word8 -> Char word8ToChar = toEnum . fromIntegral decodeC :: L.ByteString -> String decodeC = map word8ToChar . decodeW decodeBS :: L.ByteString -> L.ByteString decodeBS = L.pack . decodeW ----------------------------------------------------------------------
Jean-Nicolas Jolivet
On 2010-04-29, at 4:50 PM, Daniel Fischer wrote:
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

Am Freitag 30 April 2010 01:27:54 schrieb Daniel Fischer:
---------------------------------------------------------------------- {-# LANGUAGE BangPatterns #-}
import qualified Data.ByteString.Lazy as L import qualified Data.ByteString as S import Data.ByteString.Unsafe (unsafeAt)
Oops, import Data.ByteString.Unsafe (unsafeIndex)
escape :: Word8 -> Word8 escape = (+150)
normal :: Word8 -> Word8 normal = (+214)
decodeW :: L.ByteString -> [Word8] decodeW = dec False . L.toChunks where dec _ [] = [] dec esc (str:more) = go esc 0 where !len = S.length str {-# INLINE charAt #-} charAt :: Int -> Word8 charAt i = unsafeAt str i
charAt i = unsafeIndex str i
go !b !i | i == len = dec b more | b = escape (charAt i) : go False (i+1) | otherwise = case charAt i of 61 -> go True (i+1) c -> normal c : go False (i+1)
word8ToChar :: Word8 -> Char word8ToChar = toEnum . fromIntegral
decodeC :: L.ByteString -> String decodeC = map word8ToChar . decodeW
decodeBS :: L.ByteString -> L.ByteString decodeBS = L.pack . decodeW ----------------------------------------------------------------------
participants (9)
-
Daniel Fischer
-
Dupont Corentin
-
Hector Guilarte
-
Jean-Nicolas Jolivet
-
Jonas Almström Duregård
-
Maciej Piechotka
-
matthew coolbeth
-
Ozgur Akgun
-
Stephen Tetley