Gabriella439 / Gabriella439/Haskell-MMorph-Library

Distributive type class?

Open
#36 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Haskell
Stars
53
Forks
24
PR merge metrics
No merged PRs in 30d

Description

I found myself wanting [distribute](https://hackage.haskell.org/package/pipes-4.3.2/docs/Pipes-Lift.html#v:distribute) for a number of transformers, including transformer stacks. It seems like this is similar to [Distributive](http://hackage.haskell.org/package/distributive-0.5.2/docs/Data-Distributive.html#t:Distributive) but for transformers.

Does this makes sense as a type class?

I found myself having to reach for an associated type to implement it because it seems that a bunch of constraints are needed for every transformer in the stack. Would love to know if anyone can think of a better way as it feels like an enormous and inelegant hammer.

```hs
class Distributive g where
type Transformer
(f :: (* -> *) -> * -> *)
(g :: (* -> *) -> * -> *)
(m :: * -> *) :: Constraint

type Transformer f g m = (
Monad m
, Monad (f m)
, Monad (g m)
, Monad (f (g m))
, MonadTrans f
, MFunctor f
)

distribute :: Transformer f g m => g (f m) a -> f (g m) a

instance Distributive MaybeT where
distribute x =
lift . MaybeT . pure =<< hoist lift (runMaybeT x)

instance Distributive (ExceptT x) where
distribute x =
lift . ExceptT . pure =<< hoist lift (runExceptT x)

instance Monoid w => Distributive (WriterT w) where
distribute x =
lift . WriterT . pure =<< hoist lift (runWriterT x)

instance Distributive (ReaderT r) where
distribute x =
join . lift . ReaderT $ \r ->
pure . hoist lift $ runReaderT x r
```

For larger stacks, just an example:

```hs
newtype Example m a =
Example {
unExample :: ExceptT String (WriterT [String] (ReaderT Int m)) a
}

distributeExample :: Transformer t Example m => Example (t m) a -> t (Example m) a
distributeExample =
hoist Example .
distribute .
hoist distribute .
hoist (hoist distribute) .
unExample

instance Distributive Example where
type Transformer t Example m = (
Transformer t (ReaderT Int) m
, Transformer t (WriterT [String]) (ReaderT Int m)
, Transformer t (ExceptT String) (WriterT [String] (ReaderT Int m))
)

distribute =
distributeExample
```

I'm not sure if this is possibly related to / would help with my other question https://github.com/Gabriel439/Haskell-MMorph-Library/issues/34

I'm not tied to the names of anything here, I just wanted to have a discussion about whether this class makes sense and whether it would be useful to add to `mmorph`.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.