Proposal: Add bifunctor related classes to base

Andreas Abel andreas.abel at ifi.lmu.de
Fri Apr 25 17:14:41 UTC 2014


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

A general +1 from me.

To start the bikeshedding, let's have a look at the names in
Data.Bitraversable:

bitraverse :: Applicative f => (a -> f c) -> (b -> f d) -> t a b -> f
(t c d)
bisequenceA:: Applicative f => t (f a) (f b) -> f (t a b)
bimapM     :: Monad m => (a -> m c) -> (b -> m d) -> t a b -> m (t c d)
bisequence :: Monad m => t (m a) (m b) -> m (t a b)
bifor :: (Bitraversable t, Applicative f) => t a b -> (a -> f c) -> (b
- -> f d) -> f (t c d)
biforM :: (Bitraversable t, Monad m) => t a b -> (a -> m c) -> (b -> m
d) -> m (t c d)

I am unhappy about the name "bifor".

forM = flip mapM, so the right generalizations would be

     for   = flip map
     bifor = flip bimap

     forA   = flip mapA   = flip traverse
     biforA = flip bimapA = flip bitraverse

Unfortunately, "for" was taken for "flip traverse" by
Data.Traversable.  Instead "forA" should have been used.

In my own code, I actually define

  for = flip map

and use it in situations like

  let ys = for xs $ \ x ->
       long
       function
       body

(I never use "for" from Data.Traversable anyway, since I have not
needed yet an Applicative which is not a Monad.)

Proposal:  use "biforA" instead of "bifor".

Cheers,
Andreas

On 25.04.2014 18:36, Edward Kmett wrote:
> Biapplicative is left out because unlike the other two, it is
> underdetermined. There are at least two forms of biapplicative
> point. There are however, no such headaches with
> Bifunctor/Bifoldable/Bitraversable, which get nailed down hard by
> the laws.
> 
> A very enthusiastic +1 on the proposal from me.
> 
> -Edward
> 
>> On Apr 25, 2014, at 12:28 PM, Casey McCann
>> <cam at uptoisomorphism.net> wrote:
>> 
>> Was Biapplicative left out of the proposal because of
>> dependencies? It seems at least as useful as the others.
>> 
>> - C.
>> 
>>> On Fri, Apr 25, 2014 at 12:02 PM, Dan Doel <dan.doel at gmail.com>
>>> wrote: The previous discussion about methods on Either had some
>>> mention of adding bifunctors to base, but no one wrote up the
>>> details. So I've taken it upon myself to do so.
>>> 
>>> 
>>> The following proposal is to add some modules of the bifunctors
>>> [1] package to base, namely:
>>> 
>>> Data.Bifunctor Data.Bifoldable Data.Bitraversable
>>> 
>>> These modules contain classes and functions for working with
>>> types similar to those identified by Functor, Foldable and
>>> Traversable, except that there are parameterized by two
>>> 'element types' so to speak.
>>> 
>>> 
>>> The advantages of this change are among the following:
>>> 
>>> These are the right abstractions for many operations. For
>>> instance, Arrow is often recommended if someone wants to map
>>> over both sides (or the left side) of a pair. In fact, I'd
>>> wager that it is the single most common reason for recommending
>>> use of Arrow. But this is not really what Arrow was designed
>>> to accomplish. This is exactly what Bifunctor is for, though,
>>> and it abstracts over this kind of operation with pairs,
>>> Either, and in my experience many custom data types.
>>> 
>>> Placement in base gives a better opportunity for people to find
>>> these right abstractions. If someone goes into the
>>> documentation for Data.Either looking for a way to map both
>>> parameters, they will not, of course, be directed to the
>>> bifunctors package, even though it provides a good means of
>>> doing what they want. If Bifunctor were in base, the
>>> documentation for Either would note that it is one.
>>> 
>>> 
>>> Some things to consider:
>>> 
>>> The API of the modules will shrink a bit due to Applicative
>>> becoming a superclass of Monad in 7.10. There is no reason for
>>> a separate bitraverse and bimapM and so on. Some things will
>>> likely be renamed, as well; bisequenceA => bisequence, for
>>> instance.
>>> 
>>> The 'first' and 'second' functions in Data.Bifunctor overlap
>>> with Arrow. This actually means that they are a drop-in
>>> replacement for the commonly suggested misuse of Arrow.
>>> 
>>> None of the dependencies of the bifunctors package are needed
>>> by the modules in question. They are used for other modules, or
>>> as part of an arbitrary decision of where to put an instance.
>>> For example, the tagged dependency is used to give instances
>>> for Tagged, but these could easily be moved into the tagged
>>> package if base were to adopt these classes.
>>> 
>>> 
>>> Discussion period: 2 weeks
>>> 
>>> [1] http://hackage.haskell.org/package/bifunctors


- -- 
Andreas Abel  <><      Du bist der geliebte Mensch.

Department of Computer Science and Engineering
Chalmers and Gothenburg University, Sweden

andreas.abel at gu.se
http://www2.tcs.ifi.lmu.de/~abel/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlNamAEACgkQPMHaDxpUpLM43gCcCZJS6y4OIYtSU+RifojGKLha
C6EAoOQUhUKbJs3Dt9OZ6ryK97cGrCji
=X8HU
-----END PGP SIGNATURE-----


More information about the Libraries mailing list