
Hello,
On 8/28/06, John Hughes
No, map was never overloaded--it was list comprehensions that were overloaded as monad comprehensions in Haskell 1.4. That certainly did lead to problems of exactly the sort John M is describing.
I just checked the reports for Haskell 1.3 and 1.4 on the Haskell website and they both state that the method of 'Functor' was 'map'. I only started using Haskell towards the end of 1.4, so I don't have much experience with those versions of the language, but it seems that having an overloaded 'map' was not much of a problem if only a few people noticed.
As for an example of fmap causing trouble, recall the code I posted last week sometime:
class Foldable f where fold :: (a -> a -> a) -> a -> f a -> a
instance Foldable [] where fold = foldr
example = fold (+) 0 (fmap (+1) (return 2))
Here nothing fixes the type to be lists. When I posted this, someone called it contrived because I wrote return 2 rather than [2], which would have fixed the type of fmap to work over lists. But I don't think this is contrived, except perhaps that I reused return from the Monad class, rather than defining a new collection class with overloaded methods for both creating a singleton collection and folding an operator over a collection. This is a natural thing to do, in my opinion, and it leads directly to this example.
I don't think this example illustrates a problem with 'fmap'. The problem here is that we are using both an overloaded constructor (return) and destructor (fold), and so nothing specifies the intermediate representation. The fact that 'map' removed the ambiguity was really an accident. What if we did not need to apply a function to all elements?
example = fold (+) 0 (return 2) It seems that we could use the same argument to reason the 'return' should have the type 'a -> [a]', or that we should not overload 'fold', which with the above type seems to be fairly list specific.
-Iavor