#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
#endif
module Data.Profunctor
(
Profunctor(dimap,lmap,rmap)
, Strong(..)
, Choice(..)
, Costrong(..)
, Cochoice(..)
, Star(..)
, Costar(..)
, WrappedArrow(..)
, Forget(..)
#ifndef HLINT
, (:->)
#endif
) where
import Control.Applicative hiding (WrappedArrow(..))
import Control.Arrow
import Control.Category
import Control.Comonad
import Control.Monad (liftM, MonadPlus(..))
import Control.Monad.Fix
import Data.Distributive
import Data.Foldable
import Data.Monoid
import Data.Tagged
import Data.Traversable
import Data.Tuple
import Data.Profunctor.Unsafe
import Prelude hiding (id,(.),sequence)
#if __GLASGOW_HASKELL__ >= 708
import Data.Coerce
#else
import Unsafe.Coerce
#endif
infixr 0 :->
type p :-> q = forall a b. p a b -> q a b
newtype Star f d c = Star { runStar :: d -> f c }
instance Functor f => Profunctor (Star f) where
dimap ab cd (Star bfc) = Star (fmap cd . bfc . ab)
lmap k (Star f) = Star (f . k)
rmap k (Star f) = Star (fmap k . f)
#if __GLASGOW_HASKELL__ >= 708
p .# _ = coerce p
#else
p .# _ = unsafeCoerce p
#endif
instance Functor f => Functor (Star f a) where
fmap = rmap
instance Applicative f => Applicative (Star f a) where
pure a = Star $ \_ -> pure a
Star ff <*> Star fx = Star $ \a -> ff a <*> fx a
Star ff *> Star fx = Star $ \a -> ff a *> fx a
Star ff <* Star fx = Star $ \a -> ff a <* fx a
instance Alternative f => Alternative (Star f a) where
empty = Star $ \_ -> empty
Star f <|> Star g = Star $ \a -> f a <|> g a
instance Monad f => Monad (Star f a) where
#if __GLASGOW_HASKELL__ < 710
return a = Star $ \_ -> return a
#endif
Star m >>= f = Star $ \ e -> do
a <- m e
runStar (f a) e
instance MonadPlus f => MonadPlus (Star f a) where
mzero = Star $ \_ -> mzero
Star f `mplus` Star g = Star $ \a -> f a `mplus` g a
instance Distributive f => Distributive (Star f a) where
distribute fs = Star $ \a -> collect (($ a) .# runStar) fs
newtype Costar f d c = Costar { runCostar :: f d -> c }
instance Functor f => Profunctor (Costar f) where
dimap ab cd (Costar fbc) = Costar (cd . fbc . fmap ab)
lmap k (Costar f) = Costar (f . fmap k)
rmap k (Costar f) = Costar (k . f)
#if __GLASGOW_HASKELL__ >= 708
( #. ) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
#else
( #. ) _ = unsafeCoerce
#endif
instance Distributive (Costar f d) where
distribute fs = Costar $ \gd -> fmap (($ gd) .# runCostar) fs
instance Functor (Costar f a) where
fmap k (Costar f) = Costar (k . f)
a <$ _ = Costar $ \_ -> a
instance Applicative (Costar f a) where
pure a = Costar $ \_ -> a
Costar ff <*> Costar fx = Costar $ \a -> ff a (fx a)
_ *> m = m
m <* _ = m
instance Monad (Costar f a) where
return = pure
Costar m >>= f = Costar $ \ x -> runCostar (f (m x)) x
newtype WrappedArrow p a b = WrapArrow { unwrapArrow :: p a b }
instance Category p => Category (WrappedArrow p) where
WrapArrow f . WrapArrow g = WrapArrow (f . g)
id = WrapArrow id
instance Arrow p => Arrow (WrappedArrow p) where
arr = WrapArrow . arr
first = WrapArrow . first . unwrapArrow
second = WrapArrow . second . unwrapArrow
WrapArrow a *** WrapArrow b = WrapArrow (a *** b)
WrapArrow a &&& WrapArrow b = WrapArrow (a &&& b)
instance ArrowZero p => ArrowZero (WrappedArrow p) where
zeroArrow = WrapArrow zeroArrow
instance ArrowChoice p => ArrowChoice (WrappedArrow p) where
left = WrapArrow . left . unwrapArrow
right = WrapArrow . right . unwrapArrow
WrapArrow a +++ WrapArrow b = WrapArrow (a +++ b)
WrapArrow a ||| WrapArrow b = WrapArrow (a ||| b)
instance ArrowApply p => ArrowApply (WrappedArrow p) where
app = WrapArrow $ app . arr (first unwrapArrow)
instance ArrowLoop p => ArrowLoop (WrappedArrow p) where
loop = WrapArrow . loop . unwrapArrow
instance Arrow p => Profunctor (WrappedArrow p) where
lmap = (^>>)
rmap = (^<<)
newtype Forget r a b = Forget { runForget :: a -> r }
instance Profunctor (Forget r) where
dimap f _ (Forget k) = Forget (k . f)
lmap f (Forget k) = Forget (k . f)
rmap _ (Forget k) = Forget k
instance Functor (Forget r a) where
fmap _ (Forget k) = Forget k
instance Foldable (Forget r a) where
foldMap _ _ = mempty
instance Traversable (Forget r a) where
traverse _ (Forget k) = pure (Forget k)
class Profunctor p => Strong p where
first' :: p a b -> p (a, c) (b, c)
first' = dimap swap swap . second'
second' :: p a b -> p (c, a) (c, b)
second' = dimap swap swap . first'
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
#endif
instance Strong (->) where
first' ab ~(a, c) = (ab a, c)
second' ab ~(c, a) = (c, ab a)
instance Monad m => Strong (Kleisli m) where
first' (Kleisli f) = Kleisli $ \ ~(a, c) -> do
b <- f a
return (b, c)
second' (Kleisli f) = Kleisli $ \ ~(c, a) -> do
b <- f a
return (c, b)
instance Functor m => Strong (Star m) where
first' (Star f) = Star $ \ ~(a, c) -> (\b' -> (b', c)) <$> f a
second' (Star f) = Star $ \ ~(c, a) -> (,) c <$> f a
instance Arrow p => Strong (WrappedArrow p) where
first' (WrapArrow k) = WrapArrow (first k)
second' (WrapArrow k) = WrapArrow (second k)
instance Strong (Forget r) where
first' (Forget k) = Forget (k . fst)
second' (Forget k) = Forget (k . snd)
class Profunctor p => Choice p where
left' :: p a b -> p (Either a c) (Either b c)
left' = dimap (either Right Left) (either Right Left) . right'
right' :: p a b -> p (Either c a) (Either c b)
right' = dimap (either Right Left) (either Right Left) . left'
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
#endif
instance Choice (->) where
left' ab (Left a) = Left (ab a)
left' _ (Right c) = Right c
right' = fmap
instance Monad m => Choice (Kleisli m) where
left' = left
right' = right
instance Applicative f => Choice (Star f) where
left' (Star f) = Star $ either (fmap Left . f) (pure . Right)
right' (Star f) = Star $ either (pure . Left) (fmap Right . f)
instance Comonad w => Choice (Cokleisli w) where
left' = left
right' = right
instance Traversable w => Choice (Costar w) where
left' (Costar wab) = Costar (either Right Left . fmap wab . traverse (either Right Left))
right' (Costar wab) = Costar (fmap wab . sequence)
instance Choice Tagged where
left' (Tagged b) = Tagged (Left b)
right' (Tagged b) = Tagged (Right b)
instance ArrowChoice p => Choice (WrappedArrow p) where
left' (WrapArrow k) = WrapArrow (left k)
right' (WrapArrow k) = WrapArrow (right k)
instance Monoid r => Choice (Forget r) where
left' (Forget k) = Forget (either k (const mempty))
right' (Forget k) = Forget (either (const mempty) k)
class Profunctor p => Costrong p where
unfirst :: p (a, d) (b, d) -> p a b
unfirst = unsecond . dimap swap swap
unsecond :: p (d, a) (d, b) -> p a b
unsecond = unfirst . dimap swap swap
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
#endif
instance Costrong (->) where
unfirst f a = b where (b, d) = f (a, d)
unsecond f a = b where (d, b) = f (d, a)
instance Functor f => Costrong (Costar f) where
unfirst (Costar f) = Costar f'
where f' fa = b where (b, d) = f ((\a -> (a, d)) <$> fa)
unsecond (Costar f) = Costar f'
where f' fa = b where (d, b) = f ((,) d <$> fa)
instance Costrong Tagged where
unfirst (Tagged bd) = Tagged (fst bd)
unsecond (Tagged db) = Tagged (snd db)
instance ArrowLoop p => Costrong (WrappedArrow p) where
unfirst (WrapArrow k) = WrapArrow (loop k)
instance MonadFix m => Costrong (Kleisli m) where
unfirst (Kleisli f) = Kleisli (liftM fst . mfix . f')
where f' x y = f (x, snd y)
instance Functor f => Costrong (Cokleisli f) where
unfirst (Cokleisli f) = Cokleisli f'
where f' fa = b where (b, d) = f ((\a -> (a, d)) <$> fa)
class Profunctor p => Cochoice p where
unleft :: p (Either a d) (Either b d) -> p a b
unleft = unright . dimap (either Right Left) (either Right Left)
unright :: p (Either d a) (Either d b) -> p a b
unright = unleft . dimap (either Right Left) (either Right Left)
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 708
#endif
instance Cochoice (->) where
unleft f = go . Left where go = either id (go . Right) . f
unright f = go . Right where go = either (go . Left) id . f
instance Applicative f => Cochoice (Costar f) where
unleft (Costar f) = Costar (go . fmap Left)
where go = either id (go . pure . Right) . f
instance Traversable f => Cochoice (Star f) where
unright (Star f) = Star (go . Right)
where go = either (go . Left) id . sequence . f