Alexander Dunlap alexander.dunlap at gmail.com
Thu Feb 26 00:05:12 EST 2009

```On Wed, Feb 25, 2009 at 4:18 PM, Philip Scott <pscott at foo.me.uk> wrote:
> 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)
>

The problem is that when you go from

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

to

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

you're not just collapsing the two functions, you're changing the
definition (and type!) of "months" which you referred to within the
months function. Since months is a recursive function, you can't
necessary fold in the definition of realmonths because you want the
recursion to apply to the original months, not the original
realmonths.

As you suspected, there are better and simpler ways of doing this
available, although your way is good for getting the hang of
recursion, even though experienced haskellers really don't use
recursion all that much. (Most prefer to use functions that
encapsulate recursion *patterns* such as map, filter, folds and many
more.) You could use list concatentation while keeping the recursion,
as in

> months = range (Jan,Dec) ++ months

Even better, import Data.List and use the built-in cycle function