
Am Donnerstag, 26. Februar 2009 06:05 schrieb Alexander Dunlap:
On Wed, Feb 25, 2009 at 4:18 PM, Philip Scott
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
(http://www.haskell.org/ghc/dist/current/docs/libraries/base/Data-List.html#v...):
months = cycle (range (Jan,Dec))
One more improvement, include also Enum among the derived classes, then you can write months = cycle [Jan .. Dec] Oh, and cycle is also exported from the Prelude, so it's not necessary to import Data.List for that (though you will probably want to imoprt it anyway).
Hope that helps.
Alex
Cheers, Daniel