[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