Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1. Re:  Re: Iterating through a list of char...
      (Jean-Nicolas Jolivet)
   2. Re:  Re: Iterating through a list of char... (Daniel Fischer)
   3.  Re: Converting an imperative program to haskell
      (Maciej Piechotka)
   4. Re:  Re: Iterating through a list of char...
      (Jean-Nicolas Jolivet)


----------------------------------------------------------------------

Message: 1
Date: Thu, 29 Apr 2010 16:39:05 -0400
From: Jean-Nicolas Jolivet <[email protected]>
Subject: Re: [Haskell-beginners] Re: Iterating through a list of
        char...
To: Ozgur Akgun <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="us-ascii"

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 <[email protected]> 
> 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
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
> 
> 
> 
> -- 
> Ozgur Akgun

-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20100429/9df04236/attachment-0001.html

------------------------------

Message: 2
Date: Thu, 29 Apr 2010 22:50:21 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Re: Iterating through a list of
        char...
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="iso-8859-1"

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



------------------------------

Message: 3
Date: Thu, 29 Apr 2010 22:07:01 +0100
From: Maciej Piechotka <[email protected]>
Subject: [Haskell-beginners] Re: Converting an imperative program to
        haskell
To: [email protected]
Message-ID: <1272575221.2077.18.ca...@localhost>
Content-Type: text/plain; charset="utf-8"

On Thu, 2010-04-29 at 13:29 -0700, Hein Hundal wrote:
> 
>    I figured I should try a larger program in Haskell, so I am
> converting one of my Mathematica programs, a simulator for the 
> card game Dominion, over to Haskell.  Most of that is going well
> except for one patch of imperative code.  My Haskell version of 
> this code is ugly.  I was hoping someone could recommend a better 
> way to do it.  I will paste a simplified version of the code 
> below.  If necessary, I can provide all the other code used for 
> this simplified example (about 30 more lines of Haskell code, or 
> an equivalent program in C++ (130 lines of code). 

1. Use strong typing. Or any typing

data Card = Value `Of` Color
data Color = Spades | Hearts | Diamonds | Clubs
data Value = A | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 | J | Q | K

type Deck = [Card]

Now saying K `Of` Spades is nicer then 32 or anything. Also It allows to
have it much nicer:

check (A `Of` Clubs) = "You guessed my card!"
check _              = "Try again!"

You won't get invalid card (as 53) - it is guaranteed by the system.

2. User guards instead of nested if's:

test a b c | a == b = "Hello"
           | a == c = "Hi"
           | b == c' = "Howdy"
           | otherwise = "Goodbye"
           where c' = c + 1
vs.

test a b c = if a == b
             then "Hello"
             else if a == c
             then "Hi"
             else if b == c'
             then "Howdy"
             else "Goodbye"
             where c' = c + 1

3. Don't use too much variables. 6-8 is probably the maximum you should
deal with (human short-term memory holds about 5-10 points of entry.
Split functions into smaller functions (even in where).

4. Discard result you don't need:

isDone  (LSt gs strat iA iTh i aA iB iC bDone) = bDone
isDone  (LSt _ _ _ _ _ _ _ _ _ bDone) = bDone

5. Don't reuse the same name in the same scope (like iA as 1 and iA as
parameter to isDone).

6. While Haskell have long tradition of having short namesit is not
always good (see 3). Use them only if you are sure it is clear what they
mean:

map f (x:xs) = f x:map f xs 
-- Good - take something x from list of somethins
map _ []     = []

Regards
PS. Sorry - I haven't had time to look into code very deeply. 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
Url : 
http://www.haskell.org/pipermail/beginners/attachments/20100429/9a6d5df9/attachment-0001.bin

------------------------------

Message: 4
Date: Thu, 29 Apr 2010 17:13:21 -0400
From: Jean-Nicolas Jolivet <[email protected]>
Subject: Re: [Haskell-beginners] Re: Iterating through a list of
        char...
To: Daniel Fischer <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii

> -- 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
> 



------------------------------

_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 22, Issue 48
*****************************************

Reply via email to