[Haskell-beginners] Defeating type inference
Daniel Fischer
daniel.is.fischer at web.de
Thu Feb 26 05:09:44 EST 2009
Am Donnerstag, 26. Februar 2009 06:05 schrieb Alexander Dunlap:
> 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
>
>
(http://www.haskell.org/ghc/dist/current/docs/libraries/base/Data-List.html#v%3Acycle):
> > 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
More information about the Beginners
mailing list