Haskell and C++ program

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Haskell and C++ program

Sukit Tretriluxana
Hi all,

I was looking around Stroustrup's website and found a simple program that he showed how standard library can be used to make the program succinct and safe. See http://www.research.att.com/~bs/bs_faq2.html#simple-program. I wondered how a Haskell program equivalent to it looks like and I came up with the code below.

import qualified Control.Exception as E

main = E.catch (interact reverseDouble) (\_ -> print "format error")

reverseDouble = unlines . doIt . words
   where doIt = intro . toStrings . reverse . toDoubles . input
         toDoubles = map (read::String->Double)
         toStrings = map show
         input = takeWhile (/= "end")
         intro l = ("read " ++ (show $ length l) ++ " elements") :
                   "elements in reversed order" :

I'm not a Haskell expert and I am pretty sure that this is not the optimal form a Haskell program that's equivalent to the C++ one. So I would like to see, from the Haskell experts in this group, how else (of course better form) such a program can be written.

Thanks,
Ed



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Haskell and C++ program

Bugzilla from jonathanccast@fastmail.fm
On Wed, 2009-01-14 at 12:45 -0800, Sukit Tretriluxana wrote:

> Hi all,
>
> I was looking around Stroustrup's website and found a simple program
> that he showed how standard library can be used to make the program
> succinct and safe. See
> http://www.research.att.com/~bs/bs_faq2.html#simple-program. I
> wondered how a Haskell program equivalent to it looks like and I came
> up with the code below.
>
> import qualified Control.Exception as E
>
> main = E.catch (interact reverseDouble) (\_ -> print "format error")
>
> reverseDouble = unlines . doIt . words
>    where doIt = intro . toStrings . reverse . toDoubles . input
>          toDoubles = map (read::String->Double)
>          toStrings = map show
>          input = takeWhile (/= "end")
>          intro l = ("read " ++ (show $ length l) ++ " elements") :
>                    "elements in reversed order" :

My only criticism is that I find code written with lots of secondary
definitions like this confusing; so I would inline most of the
definitions:

  reverseDouble =
        unlines
      . intro
      . map show
      . reverse
      . map (read :: String -> Double)
      . takeWhile (/= "end")
      . words
    where
      intro l =
        ("read " ++ show (length l) ++ " elements") :
        "elements in reversed order" :
        l

I observe also in passing that the cast on read is somewhat inelegant;
in a real application, the consumer of map read's output would specify
its type sufficiently that the cast would be un-necessary.

For example, the program could be specified to compute sines instead:

main = E.catch (interact unlines . intro . map (show . sin . read) .
words) $ \ _ -> print "format error"
  where
    intro l =
      ("read " ++ show (length l) ++ " arguments") :
      "computed sins" :
      l

(Others will no doubt object to the use of lazy I/O.  I disagree in
principle with those objections.)

jcc

PS Stroustrup's comments about vectors are at best half right; push_back
may extend the vector's length correctly, but operator[] on a vector
certainly does not do bounds checking.


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Haskell and C++ program

Peter Verswyvelen-2

PS Stroustrup's comments about vectors are at best half right; push_back
may extend the vector's length correctly, but operator[] on a vector
certainly does not do bounds checking.

Sure it does, depending on how you configured the STL library. But this is off topic :)



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re[2]: Haskell and C++ program

Bulat Ziganshin-2
In reply to this post by Bugzilla from jonathanccast@fastmail.fm
Hello Jonathan,

Thursday, January 15, 2009, 1:41:23 AM, you wrote:

>   reverseDouble =
>         unlines
>       . intro
>       . map show
>       . reverse
>       . map (read :: String -> Double)
>       . takeWhile (/= "end")
>       . words

using arrows, this may be reversed:

  reverseDouble =
          words
      >>> takeWhile (/= "end")
      ...

> I observe also in passing that the cast on read is somewhat inelegant;
> in a real application, the consumer of map read's output would specify
> its type sufficiently that the cast would be un-necessary.

in small scripts explicit read casts are rather common


--
Best regards,
 Bulat                            mailto:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Haskell and C++ program

Yitzchak Gale
In reply to this post by Sukit Tretriluxana
Sukit Tretriluxana:
> I was looking around Stroustrup's website and found
> a simple program... I wondered how a Haskell
> program equivalent to it looks like...

> main = E.catch (interact reverseDouble) (\_ -> print "format error")
>          toDoubles = map (read::String->Double)

For a "safe" program in Haskell, we would not normally use
an unsafe function like "read", and then try to rescue it by
catching IO exceptions. Instead, we would write the program
safely to begin with. Something like this (building on
Jonathan's idea):

import Data.Maybe (listToMaybe)

main = interact reverseDouble

reverseDouble =
  unlines . intro .
  maybe ["format error"] (map show . reverse) .
  mapM (readMaybe :: String -> Maybe Double) .
  takeWhile (/= "end") . words
   where
     intro l =
       ("read " ++ show (length l) ++ " elements") :
       "elements in reversed order" :
       l

readMaybe :: Read a => String -> Maybe a
readMaybe = listToMaybe . map fst . reads

The function "readMaybe" returns the pure value
"Nothing" if there is a format error instead of throwing
an IO exception. It has been proposed to make it part
of the standard libraries - I'm not sure what the status
is of that process.

Regards,
Yitz
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Haskell and C++ program

Heinrich Apfelmus
In reply to this post by Bugzilla from jonathanccast@fastmail.fm
Jonathan Cast wrote:

>   reverseDouble =
>         unlines
>       . intro
>       . map show
>       . reverse
>       . map (read :: String -> Double)
>       . takeWhile (/= "end")
>       . words
>     where
>       intro l =
>         ("read " ++ show (length l) ++ " elements") :
>         "elements in reversed order" :
>         l

This can be simplified to

  ... . map show . reverse . map read . ...

 = { map f . reverse = reverse . map f }

  ... . reverse . map show . map read . ...

 = { map f . map g = map (f . g) }

  ... . reverse . map (show . read) . ...

 = { show . read = id }

  ... . reverse . map id . ...

 = { map id = id }

  ... . reverse . ...

In other words,

  reverseDouble =
    unlines. intro . reverse . takeWhile (/= "end") . words
    where
      intro xs =
        ("read " ++ show (length xs) ++ " elements") :
        "elements in reversed order" :
        xs

And the doubles disappeared completely. :)


Regards,
H. Apfelmus

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Haskell and C++ program

Eugene Kirpichov
Well, your program is not equivalent to the C++ version, since it
doesn't bail on incorrect input.

2009/1/15 Apfelmus, Heinrich <[hidden email]>:

> Jonathan Cast wrote:
>>   reverseDouble =
>>         unlines
>>       . intro
>>       . map show
>>       . reverse
>>       . map (read :: String -> Double)
>>       . takeWhile (/= "end")
>>       . words
>>     where
>>       intro l =
>>         ("read " ++ show (length l) ++ " elements") :
>>         "elements in reversed order" :
>>         l
>
> This can be simplified to
>
>  ... . map show . reverse . map read . ...
>
>  = { map f . reverse = reverse . map f }
>
>  ... . reverse . map show . map read . ...
>
>  = { map f . map g = map (f . g) }
>
>  ... . reverse . map (show . read) . ...
>
>  = { show . read = id }
>
>  ... . reverse . map id . ...
>
>  = { map id = id }
>
>  ... . reverse . ...
>
> In other words,
>
>  reverseDouble =
>    unlines. intro . reverse . takeWhile (/= "end") . words
>    where
>      intro xs =
>        ("read " ++ show (length xs) ++ " elements") :
>        "elements in reversed order" :
>        xs
>
> And the doubles disappeared completely. :)
>
>
> Regards,
> H. Apfelmus
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Haskell and C++ program

Heinrich Apfelmus
Eugene Kirpichov wrote:
> Well, your program is not equivalent to the C++ version, since it
> doesn't bail on incorrect input.

Oops. That's because my assertion

   show . read = id

is wrong. We only have

   read . show  = id
   show . read <= id  (in the "less defined than" sense)


Regards,
H. Apfelmus

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re[2]: Re: Haskell and C++ program

Bulat Ziganshin-2
In reply to this post by Eugene Kirpichov
Hello Eugene,

Thursday, January 15, 2009, 3:27:59 PM, you wrote:

but at least "length.map show" is eq to length :)

> Well, your program is not equivalent to the C++ version, since it
> doesn't bail on incorrect input.

> 2009/1/15 Apfelmus, Heinrich <[hidden email]>:
>> Jonathan Cast wrote:
>>>   reverseDouble =
>>>         unlines
>>>       . intro
>>>       . map show
>>>       . reverse
>>>       . map (read :: String -> Double)
>>>       . takeWhile (/= "end")
>>>       . words
>>>     where
>>>       intro l =
>>>         ("read " ++ show (length l) ++ " elements") :
>>>         "elements in reversed order" :
>>>         l
>>
>> This can be simplified to
>>
>>  ... . map show . reverse . map read . ...
>>
>>  = { map f . reverse = reverse . map f }
>>
>>  ... . reverse . map show . map read . ...
>>
>>  = { map f . map g = map (f . g) }
>>
>>  ... . reverse . map (show . read) . ...
>>
>>  = { show . read = id }
>>
>>  ... . reverse . map id . ...
>>
>>  = { map id = id }
>>
>>  ... . reverse . ...
>>
>> In other words,
>>
>>  reverseDouble =
>>    unlines. intro . reverse . takeWhile (/= "end") . words
>>    where
>>      intro xs =
>>        ("read " ++ show (length xs) ++ " elements") :
>>        "elements in reversed order" :
>>        xs
>>
>> And the doubles disappeared completely. :)
>>
>>
>> Regards,
>> H. Apfelmus
>>
>> _______________________________________________
>> Haskell-Cafe mailing list
>> [hidden email]
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe


--
Best regards,
 Bulat                            mailto:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Haskell and C++ program

Derek Elkins
In reply to this post by Heinrich Apfelmus
On Thu, 2009-01-15 at 13:40 +0100, Apfelmus, Heinrich wrote:

> Eugene Kirpichov wrote:
> > Well, your program is not equivalent to the C++ version, since it
> > doesn't bail on incorrect input.
>
> Oops. That's because my assertion
>
>    show . read = id
>
> is wrong. We only have
>
>    read . show  = id
>    show . read <= id  (in the "less defined than" sense)

No, you only have
read . show = id which often doesn't hold in practice.
show . read </= id

Assuming the first identity holds, you do of course have show . read .
show = show and this probably holds even in most cases where read . show
= id does not hold.


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Haskell and C++ program

S. Doaitse Swierstra

On 17 jan 2009, at 22:22, Derek Elkins wrote:

> On Thu, 2009-01-15 at 13:40 +0100, Apfelmus, Heinrich wrote:
>> Eugene Kirpichov wrote:
>>> Well, your program is not equivalent to the C++ version, since it
>>> doesn't bail on incorrect input.
>>
>> Oops. That's because my assertion
>>
>>   show . read = id
>>
>> is wrong. We only have
>>
>>   read . show  = id
>>   show . read <= id  (in the "less defined than" sense)
>
> No, you only have
> read . show = id which often doesn't hold in practice.
> show . read </= id

You do not even have that; the read may remove surplus parentheses  
which will not be reinserted by the show.

  Doaitse


>
>
> Assuming the first identity holds, you do of course have show . read .
> show = show and this probably holds even in most cases where read .  
> show
> = id does not hold.
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Haskell and C++ program

Derek Elkins
On Mon, 2009-01-19 at 22:12 -0500, S. Doaitse Swierstra wrote:

> On 17 jan 2009, at 22:22, Derek Elkins wrote:
>
> > On Thu, 2009-01-15 at 13:40 +0100, Apfelmus, Heinrich wrote:
> >> Eugene Kirpichov wrote:
> >>> Well, your program is not equivalent to the C++ version, since it
> >>> doesn't bail on incorrect input.
> >>
> >> Oops. That's because my assertion
> >>
> >>   show . read = id
> >>
> >> is wrong. We only have
> >>
> >>   read . show  = id
> >>   show . read <= id  (in the "less defined than" sense)
> >
> > No, you only have
> > read . show = id which often doesn't hold in practice.
> > show . read </= id
>
> You do not even have that; the read may remove surplus parentheses  
> which will not be reinserted by the show.
>
>   Doaitse
>

My notation is show . read is not less than or equal to id.  That covers
that case.  The particular example I was thinking of was actually simply
whitespace.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe