Haskell 98 Report

Mark Tullsen tullsen@cs.yale.edu
Thu, 31 May 2001 15:04:02 -0400


So much for my small, innocuous, non controversial suggestion :-).

Fergus Henderson wrote:
> 
> On 31-May-2001, Simon Peyton-Jones <simonpj@microsoft.com> wrote:
> > We should either generalise all three
> >       deleteBy
> >       deleteFirstsBy
> >       intersectBy
> > or none.
> >
> > In favour:
> >       the more general types are occasionally useful
> >       no programs stop working
> 
> Actually some programs will stop working, because the types will be
> underconstrained, so the compiler won't know how to satisfy some type class
> constraint.
> 
> For example:
> 
>         import List
>         main = print (deleteBy (\x _y -> x > 0) 1 [])
> 
> With the generalized type, you'd get an unresolved `Show' constraint.

That's a good point Fergus, I hadn't noticed the potential problem here.

> The number of real programs for which this is a problem is most likely very
> small, and the work-around (typically just adding an explicit type
> qualification) is not hard once you understand what the problem is, but
> figuring out what the problem is could take some time.

My intuition (whatever it's worth) tells me that the real programs that
would be affected are close to nil.  Would you agree?

> Since it does break some obscure programs, and since it's easy enough
> for programmers who want a generalized version to just cut and paste
> the code from the Haskell report and give it a more general type signature,

Sure, it's easy enough, but one of the reasons I like Haskell so much over
languages like C is that I almost never have to resort to programming by 
"cut and paste".

I generally prefer to give the most general type signature for each definition.
It makes programs more robust. It gives a stronger "free theorem"; in other words,
I can tell more about the function by just looking at the type.  For instance ...

Tom Pledger wrote:
> Malcolm Wallace writes:
>  :
>  | >      intersectBy :: (a -> b -> Bool) -> [a] -> [b] -> [a]
>  |
>  | Although curiously, its dual 'unionBy' cannot also take the more
>  | general type
>  |
>  |         unionBy :: (a -> b -> Bool) -> [a] -> [b] -> [a]
>  |
>  | at least, not with its current specification in terms of 'nubBy'.
> 
> That suggests a reason to leave the type of intersectBy alone - the
> generalisation would arbitrarily favour the first list's type over the
> second list's type.  To me, the word "intersect" implies symmetry.

But to me it seems a good reason to change the type of intersectBy:
the definition isn't really symmetric, so why should the type signature
be symmetric?

- Mark