[Haskell-cafe] Help understanding Haskell runtime costs
Henning Thielemann
schlepptop at henning-thielemann.de
Thu Aug 11 18:23:58 CEST 2011
On 09.08.2011 01:43, Thiago Negri wrote:
> Hello all,
>
> I'm relatively new to Haskell and trying to solve some online judge's
> problems in it.
> One of the problems is to say if a given sentence is a tautogram or not.
> A tautogram is just a sentence with all the words starting with the same letter.
>
> My first try (solution is ok) was to do it as haskeller as possible,
> trying to overcome my imperative mind.
> But it did bad at performance (0.30 secs of runtime, 4.6 mb of memory):
>
> -- code start
> import Data.Char (toLower)
>
> main = getContents>>= mapM_ (putStrLn . toStr . isTautogram . words)
> . takeWhile (/= "*") . lines
That's still imperative! :-)
How about 'interact' and using 'unlines' instead of 'putStrLn' ?
> toStr :: Bool -> [Char]
You may want to write String instead of [Char] for clarity.
> toStr True = "Y"
> toStr False = "N"
>
> isTautogram :: [[Char]] -> Bool
> isTautogram (x:[]) = True
I assume this case is not necessary, since all [] == True anyway.
> isTautogram (x:xs) = all ((== firstChar) . toLower . head) xs
> where firstChar = toLower . head $ x
It is maybe more elegant, not to compare all words with the first one,
but to compare adjacent words in the list:
all (zipWith (...) xs (drop 1 xs))
> Note that the only thing that changed between the two tries was the main-loop.
> The second version runs faster (got 0.11 secs) and with less memory (3.6 mb)
>
> Can someone explain to me what is really going on?
> Maybe pointing out how I can achieve these optimizations using
> profiling information...
Interesting observation. I do not see a problem quickly.
More information about the Haskell-Cafe
mailing list