Gabriella439 / Gabriella439/Haskell-MMorph-Library
Distributive type class?
- 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.