[Haskell-beginners] Parsing a file with data divided into sections

Magnus Therning magnus at therning.org
Wed Feb 4 05:02:30 EST 2009


On Wed, Feb 4, 2009 at 1:58 AM, Patrick LeBoutillier
<patrick.leboutillier at gmail.com> wrote:
> Hi all,
>
> I wanted to parse a file that looks like this:
>
> MONDAY
>        JOHN
>        JIM
>        LINDA
> TUESDAY
>        BILL
>        BOB
> WEDNESDAY
> THURSDAY
>        SAM
>        TODD
>        LARRY
>        LUKE
> FRIDAY
>        TED
>
> in order to count the number of people for each day. After a (very)
> long time and a lot of trial and
> error, I managed to do it with this program:
>
> import Char (isSpace)
>
> main = interact (unlines . countSections . lines)
>   where countSections = map (show) . snd . foldr compileSections (0, [])
>         compileSections line (n, acc) =
>             if isSection line
>             then (0, (line, n) : acc)
>             else (n + 1, acc)
>         isSection line = not . isSpace . head $ line
>
> which outputs:
>
> ("MONDAY",3)
> ("TUESDAY",2)
> ("WEDNESDAY",0)
> ("THURSDAY",4)
> ("FRIDAY",1)
>
> I had quite a hard time figuring out how to keep count of the number
> of records in each sections.
> Is there a more obvious way to handle these types of problems? Are
> there some builtins that could
> of made it easier?

I think that you've pretty much used accumulators in the way they most
often are used.  In many cases you don't _have_ to keep count though.
Here's one way to get the same result, but without keeping count:

countDays [] = []
countDays ls = let
        day = head ls
        count = length $ takeWhile (isSpace . head) $ tail ls
    in (day, count) : countDays (drop (1 + count) ls)

main = interact (unlines . map show . countDays . lines)

> In Perl I would probably have used a hash and a variable to keep count
> of the current day, incrementing
> the hash value for each person until I got to the next day, but it's
> not obvious to me how to transpose this
> technique to functional programming.

Often transposing from imperative to functional isn't what you want to
do.  One of the arguments for learning both imperative and functional
languages is that they approach problems differently, resulting in
different solutions.  I suspect you will find Haskell, and indeed any
functional language, difficult to use if you try to "think
imperative".  It takes time to learn new ways to think about problems,
but in the end you'll never look at things the same way again :-)

/M

-- 
Magnus Therning                        (OpenPGP: 0xAB4DFBA4)
magnus@therning.org          Jabber: magnus@therning.org
http://therning.org/magnus         identi.ca|twitter: magthe


More information about the Beginners mailing list