Polymorphism in the Prelude

Mateusz Kowalczyk fuuzetsu at fuuzetsu.co.uk
Tue Jun 24 10:42:32 UTC 2014


On 06/18/2014 09:04 PM, Daniel Gorín wrote:
> 
> On 18 Jun 2014, at 12:09, Yitzchak Gale <gale at sefer.org> wrote:
> 
>> Richard Eisenberg wrote:
>>> Having lots of polymorphism in the Prelude is great, but for two problems:
>>> 1) It's very confusing to novices.
>>> 2) In the case of using Control.Category definitions: kind-polymorphism is
>>> not portable
>>>
>>> I wish to ignore (2) for now, as it's a smaller concern given that it
>>> affects only a portion of the proposed changes.
>>
>> In my opinion, Richard missed the most important reason:
>>
>> 3) Gratuitous polymorphism makes code much less readable
>>  and much costlier to maintain, usually for almost no gain.
> 
> The crucial problem for me would be:
> 
> 4) Instance-based APIs are currently very difficult to  discover.
> 
> Just to name a few examples of useful but hidden functions:
> 
> - looking at the Haddock for Data.Maybe, it is very hard to find:
>     forM :: Monad m => Maybe a -> (a -> m b) -> m (Maybe b)
> 
> - looking at the Haddock for Data.Either, it is *impossible* to discover:
>     (+++) :: (a -> a') -> (b -> b') -> Either a b -> Either a’ b’
> 
> - looking at the Haddock for Data.Tuple, it is *impossible* to discover:
>    (***) :: (a -> a’) -> (b -> b’) -> (a,b) -> (a’,b’)
> 
> - looking at the Haddock for Data.Map , it is hard to spot:
>    sequenceA_ :: Applicative f => Map a (f b) -> f ()
> 
> It helps if one knows in advance what Foldable, Traversable or Arrow are, but it is
> easier to  understand a generalization if you were first exposed to concrete cases.
> So whenever we replace a concrete function by a typeclass-based generalization,
> we hurt the available documentation and make the learning curve even steeper.
> 
> This is perhaps “just” a tooling problem that could be solved by haddock in some
> way, but until then it is my main concern with these proposals.
> 

Regarding Haddock doing something:

Do you have anything specific in mind here? At first I was just going to
dismiss this as wishful thinking but perhaps we could actually do
something about this.

Maybe we could provide ‘alternative’ signatures which would make types
more specific with some (which? all of known ones?) instances.

Example:

fmap :: Functor f => (a -> b) -> f a -> f b

knowing that Maybe and [] and (Either c) are all instance of Functor,
maybe there could be an option to show extra signatures such as

fmap :: (a -> b) -> Maybe a -> Maybe b
fmap :: (a -> b) -> [a] -> [b]
fmap :: (a -> b) -> Either c a -> Either c b

Is this what you had in mind? I thought lambdabot on IRC was able to do
this but after asking around, it seems I was mistaken.

I can certainly see its usefulness but it seems tricky to implement:

Which instances to use? Should a user be able to say which instances
should show in docs and if yes, how? How to implement this in the
back-end? How should it look to the user? A something that is a stretch
would be allowing the user to specify what ‘f’ was on the page and have
it perform syntax substitution but that seems less useful: more user
work and if they are going to do that then they might as well load it up
into GHCi.

If this isn't what you meant then I'd be interested to hear. A much
easier way of course is to simply document some example instances. I
think pipes does something like this as you can see at [1]. The downside
of course is that it's not automated, has to be manually kept up to date
and the implementer might not have thought about a particular instance
you want to see.

[1]: https://hackage.haskell.org/package/pipes-4.1.2/docs/Pipes.html#v:for

> Daniel
> 
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
> 


-- 
Mateusz K.


More information about the Libraries mailing list