{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
module Data.Profunctor.Joinable where

import Data.Profunctor

class Profunctor p => Joinable p m | p -> m where
  join' :: p a (m b) -> p a b

instance Monad m => Joinable (Star m) m where
  join' :: Star m a (m b) -> Star m a b
join' (Star f :: a -> m (m b)
f) = (a -> m b) -> Star m a b
forall (f :: * -> *) d c. (d -> f c) -> Star f d c
Star (m (m b) -> m b
forall (m :: * -> *) b. Monad m => m (m b) -> m b
join (m (m b) -> m b) -> (a -> m (m b)) -> a -> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m (m b)
f)
    where
      join :: m (m b) -> m b
join m :: m (m b)
m = m (m b)
m m (m b) -> (m b -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m b -> m b
forall a. a -> a
id

instance Monad m => Joinable (Forget (m r)) m where
  join' :: Forget (m r) a (m b) -> Forget (m r) a b
join' (Forget f :: a -> m r
f) = (a -> m r) -> Forget (m r) a b
forall r a b. (a -> r) -> Forget r a b
Forget a -> m r
f