Working character by character in Haskell

Andre W B Furtado
Fri, 19 Oct 2001 03:14:42 -0300

Humn... I agree with both of you, Albert and Tom. I started it from the
beginning, using map and don't using reverse anymore. But the C program is
still 7x faster than the Haskell one. Here is the code of the Haskell

main :: IO ()
main = do
 bmFile <- openFileEx "in.txt" (BinaryMode ReadMode)
 bmString <- hGetContents bmFile
 writeFile "out.txt" (map inc bmString)
 hClose bmFile

inc :: Char -> Char
inc a = toEnum ((fromEnum a) + 1)

And now the C program:

#include <stdio.h>

void main()
 FILE *in, *out;
 char ch;

 in = fopen("in.txt","rb");
 out = fopen("out.txt","wb");

 while ( (ch=getc(in)) != EOF)
  putc(ch + 1,out);

As you noticed, the main idea here is to increment the character by "one".
Is the Haskell program now a nice translation of the C program? If it is (I
think so...) why is the C program so much faster than it?

Thanks again,
-- Andre

----- Original Message -----
From: Albert Lai <>
To: <>
Sent: Thursday, October 18, 2001 9:42 PM
Subject: Re: Working character by character in Haskell

> "Andre W B Furtado" <> writes:
> [...]
> > For example, suppose function doSomeStuffWith returns its own parameter.
> > Using a 1.5MB file in this case, the Haskell program ends in almost 5
> > seconds, while the C program ends in less than 0.5 seconds... Is my
> > program too bad implemented? (I'm using GHC 4.08-1 under a Windows 98
> > platform.)
> I indeed think that your Haskell program is inefficient and is not a
> translation of your C program.  It reverses a huge string, which takes
> not only execution time but also garbage collection time and memory,
> which entails even more time for OS overhead and swapping out other
> things in the physical memory.
> (Many programmers complain "my linear-time algorithm takes just 1
> second on a 100M list, so why is it taking 5 seconds on a 200M list?"
> They forget that because of issues such as cache locality and virtual
> memory, their computers do not scale.)
> I am wondering that if doSomeStuffWith is pure-functional, why are you
> writing and using copyFile instead of just using map?  I mean:
> main :: IO ()
> main = do
>  bmFile <- openFileEx "in.txt" (BinaryMode ReadMode)
>  bmString <- hGetContents bmFile
>  writeFile "out.txt" (map doSomestuffWith bmString)
>  hClose bmFile
> Because both hGetContents and map are lazy and use O(1) memory, this
> program behaves exactly as your C program plus occasional garbage
> collections that don't hurt too much.  In partcular, the OS will see
> no difference (although the cache does).