[Haskell-beginners] Defeating type inference

Philip Scott pscott at foo.me.uk
Wed Feb 25 19:18:15 EST 2009

Well, either that or I being an idiot.

Here's a little example. Let us say you had a datatype 'Month'*

data Month = Jan
       |     Feb
       |     Mar
       |     Apr
       |     May
       |     Jun
       |     Jul
       |     Aug
       |     Sep
       |     Oct
       |     Nov
       |     Dec
       deriving(Show, Eq, Ord, Ix)

What I would like to make is an infinite lazy list of months (called, 
rather imaginitively I thought, 'months') that keeps wrapping around. 
That is to say, it would make a list like this

[Jan, Feb, ...., Nov, Dec, Jan, Feb, ....., Nov, Dec, ... ad infinitum ]

I am sure you get the picture. My first stab was this:

months = range (Jan, Dec) : months

But of course, what you get here is a list of lists, with each element 
being a list of [Jan, Feb, ...., Dec]

So I puzzled for a little bit about how to do this in the most Haskelly 
way and I thought of this

months = concat (range (Jan, Dec) : months)

Which should work, right**

But the type checker is not pleased at all and complains:

        Couldn't match expected type `[Month]'
               against inferred type `Month'
          Expected type: [[Month]]
          Inferred type: [Month]
        In the expression: concat (range (Jan, Dec) : months)
        In the definition of `months':
            months = concat (range (Jan, Dec) : months)

However, if you use the first definition and make a second function:

months = range (Jan, Dec) : months
realmonths = concat(months)

It is happy and does what one might expect. I thought perhaps I was just 
confusing the inference engine so I tried a liberal sprinkling of :: 
operators to make my intentions clear, but it still wasn't having any of it.

Any thoughts welcomed!

- Philip

* I am aware that there is plenty of code to handle dates and times 
already written, probably much more nicely than mine - this is just a 
project I have been hacking at to get to grips with things.
** though I am pretty sure this is the Wrong Way to do this. I suspect 
concat takes O(n) time - more elegant approaches would be welcomed!

More information about the Beginners mailing list