Proposal: refactor Arrow class

Edward A Kmett ekmett at gmail.com
Thu Jan 10 01:05:53 CET 2013


The situation with Functor involves three parties, me writing lens combinators that are agnostic to the Functor chosen, the user, and the libraries they use. Nobody is in the proper position to creat unorphaned instances of these new classes. I routinely use the lens to augment fuctionality from libraries that do not depend on lens.

With Profunctor, currently I provide the package, and so I am both the combinator author and currently the library author. If you decompose Profunctor and move it into base all of a sudden, I'm in the same boat as with Functor. 

Spontaneously users are able to use any Arrow at all for

type Iso s t a b = forall p. (Profunctor p, Functor p) => p a (f b) -> p s (f t)

which is great! but it pretty much would force me to give the current efficiency gains I get in practice, or draw silly distinctions between FastIso and Iso.

The extra instance quickly becomes 200 combinators that differ solely in this one detail. When the alternative costs me nothing.

I'm currently strongly -1 on PostArrow or a lobotomized Profunctor.

PreArrow doesn't really affect me. I'm happily +1 on that.

Sent from my iPhone

On Jan 9, 2013, at 11:10 AM, Ross Paterson <ross at soi.city.ac.uk> wrote:

> On Wed, Jan 09, 2013 at 07:57:02AM +0000, Edward Kmett wrote:
>> It lets you lift core `cast`'s out over the functorial argument,
>> which isn't something I can do from outside of the class. If I tried
>> to write something where the end user hands me an arbitrary Functor (or
>> Profunctor) and I unsafeCoerce to cast, this would expose unsafeCoerce
>> to the end user. 
>> 
>> The implementation trick is to place these extra methods in the class
>> but hidden in an explicitly Unsafe module and with default definitions
>> that are correct but slow.
>> 
>> Then the provider of the functor-like class can explicitly import that
>> module, and implement the methods, and mark his module Trustworthy. He
>> hasn't exposed unsafeCoerce to the end user, they have to import an
>> explicitly Unsafe module to get access to it, incurring the obligation
>> themselves to provide something that is operationally id or a cast.
>> 
>> This enables you to have the efficient implementation but guarded by an
>> explicitly Unsafe module so the end user has to import that to get the
>> efficient functionality, but you can discharge your obligations locally.
>> 
>> Similarly you can discharge the obligation about the representation
>> of the operation you are passing at the use site. This means that you
>> can reason about these separately.
> 
> You could achieve the same effects by splitting off (.#) and (#.) into
> a subclass, couldn't you?  It would just mean more instance declarations.
> 
> _______________________________________________
> Libraries mailing list
> Libraries at haskell.org
> http://www.haskell.org/mailman/listinfo/libraries



More information about the Libraries mailing list