distributive icon indicating copy to clipboard operation
distributive copied to clipboard

Add Applicative and/or Monad superclasses to Distributive?

Open ekmett opened this issue 9 years ago • 8 comments

They are implied by the theory.

ekmett avatar Dec 06 '15 03:12 ekmett

This is pretty surprising to me, since some datatypes which currently have Distributive instances do not have Monad instances! For example, Compose from transformers.

RyanGlScott avatar Dec 08 '15 17:12 RyanGlScott

We could likely leave off with just Applicative, and not do the Monad.

ekmett avatar Dec 08 '15 17:12 ekmett

(and Compose does have that instance.)

The problem is that Distributive isn't strong enough to 'zip' despite the conditions necessary for the existence of an instance saying it should be able to.

ekmett avatar Dec 08 '15 17:12 ekmett

But that still feels funny to me, since the documentation in adjunctions claims that every Distributive instance admits a Representable instance, which gives rise to an implementation of bind. Does adjunctions' bind not guarantee adherence to the Monad laws?

The problem is that Distributive isn't strong enough to 'zip' despite the conditions necessary for the existence of an instance saying it should be able to.

It isn't?

RyanGlScott avatar Dec 08 '15 17:12 RyanGlScott

Representable is strong enough. Distributive doesn't let you know what the representation is.

I'd like more things to be able to work with just a Haskell-98 distributive constraint.

The bind in adjunctions guarantees adherence to the Monad laws. However it isn't suitable for Compose as there are potentially multiple instances of Monad for Compose f g depending on the properties of f and g. e.g. left adjoints also compose, so do any pair of functors with a distributive law (MaybeT, EitherT, ReaderT, WriterT all come from these) or an absorption law, etc.

So my goal is to be able to keep as many instances as possible while amping up the power of Distributive to where it can actually be used in a non-linear situation.

ekmett avatar Dec 08 '15 17:12 ekmett

Any Functor that is both Applicative and Distributive is also a Monad:

bindDistributive :: (Applicative m, Distributive m) => m a -> (a -> m b) -> m b
bindDistributive m f = m <**> distribute f

It won't let you define the Monad instance for Compose, but you could probably write a newtype wrapper for it.

Zemyla avatar Nov 28 '17 20:11 Zemyla

Oh, and all Distributive instances are also MonadFixs:

mfixDistributive :: Distributive m => (a -> m a) -> m a
mfixDistributive = fmap fix . distribute

Zemyla avatar Oct 05 '18 08:10 Zemyla

The current plan is to package a "Dist" newtype that can be used via Deriving Via to get access to all of these instances for your data type if you want them, but to not require them as superclasses, to maintain compatibility with things like Compose.

On Fri, Oct 5, 2018 at 4:10 AM Zemyla [email protected] wrote:

Oh, and all Distributive instances are also MonadFixs:

mfixDistributive :: Distributive m => (a -> m a) -> m a mfixDistributive = fmap fix . distribute

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/ekmett/distributive/issues/12#issuecomment-427281997, or mute the thread https://github.com/notifications/unsubscribe-auth/AASmEbnKg6qVZpI56ct05ghPLSsPtuefks5uhxPegaJpZM4Gvksn .

ekmett avatar Oct 05 '18 09:10 ekmett