#if __GLASGOW_HASKELL__ >= 702 && __GLASGOW_HASKELL__ <= 708
#endif
module Data.Profunctor.Yoneda
( Yoneda(..), extractYoneda, duplicateYoneda
, Coyoneda(..), returnCoyoneda, joinCoyoneda
) where
import Control.Category
import Data.Profunctor
import Data.Profunctor.Monad
import Data.Profunctor.Traversing
import Data.Profunctor.Unsafe
import Prelude hiding (id,(.))
#if __GLASGOW_HASKELL__ >= 708
import Data.Coerce
#else
import Unsafe.Coerce
#endif
newtype Yoneda p a b = Yoneda { runYoneda :: forall x y. (x -> a) -> (b -> y) -> p x y }
extractYoneda :: Yoneda p a b -> p a b
extractYoneda p = runYoneda p id id
duplicateYoneda :: Yoneda p a b -> Yoneda (Yoneda p) a b
duplicateYoneda p = Yoneda $ \l r -> dimap l r p
instance Profunctor (Yoneda p) where
dimap l r p = Yoneda $ \l' r' -> runYoneda p (l . l') (r' . r)
lmap l p = Yoneda $ \l' r -> runYoneda p (l . l') r
rmap r p = Yoneda $ \l r' -> runYoneda p l (r' . r)
#if __GLASGOW_HASKELL__ >= 708
( .# ) p _ = coerce p
( #. ) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
#else
( .# ) p _ = unsafeCoerce p
( #. ) _ = unsafeCoerce
#endif
instance Functor (Yoneda p a) where
fmap f p = Yoneda $ \l r -> runYoneda p l (r . f)
instance ProfunctorFunctor Yoneda where
promap f p = Yoneda $ \l r -> f (runYoneda p l r)
instance ProfunctorComonad Yoneda where
proextract p = runYoneda p id id
produplicate p = Yoneda $ \l r -> dimap l r p
instance ProfunctorMonad Yoneda where
proreturn p = Yoneda $ \l r -> dimap l r p
projoin p = runYoneda p id id
instance (Category p, Profunctor p) => Category (Yoneda p) where
id = Yoneda $ \l r -> dimap l r id
p . q = Yoneda $ \ l r -> runYoneda p id r . runYoneda q l id
instance Strong p => Strong (Yoneda p) where
first' = proreturn . first' . extractYoneda
second' = proreturn . second' . extractYoneda
instance Choice p => Choice (Yoneda p) where
left' = proreturn . left' . extractYoneda
right' = proreturn . right' . extractYoneda
instance Costrong p => Costrong (Yoneda p) where
unfirst = proreturn . unfirst . extractYoneda
unsecond = proreturn . unsecond . extractYoneda
instance Cochoice p => Cochoice (Yoneda p) where
unleft = proreturn . unleft . extractYoneda
unright = proreturn . unright . extractYoneda
instance Closed p => Closed (Yoneda p) where
closed = proreturn . closed . extractYoneda
instance Mapping p => Mapping (Yoneda p) where
map' = proreturn . map' . extractYoneda
instance Traversing p => Traversing (Yoneda p) where
traverse' = proreturn . traverse' . extractYoneda
wander f = proreturn . wander f . extractYoneda
data Coyoneda p a b where
Coyoneda :: (a -> x) -> (y -> b) -> p x y -> Coyoneda p a b
returnCoyoneda :: p a b -> Coyoneda p a b
returnCoyoneda = Coyoneda id id
joinCoyoneda :: Coyoneda (Coyoneda p) a b -> Coyoneda p a b
joinCoyoneda (Coyoneda l r p) = dimap l r p
instance Profunctor (Coyoneda p) where
dimap l r (Coyoneda l' r' p) = Coyoneda (l' . l) (r . r') p
lmap l (Coyoneda l' r p) = Coyoneda (l' . l) r p
rmap r (Coyoneda l r' p) = Coyoneda l (r . r') p
#if __GLASGOW_HASKELL__ >= 708
( .# ) p _ = coerce p
( #. ) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
#else
( .# ) p _ = unsafeCoerce p
( #. ) _ = unsafeCoerce
#endif
instance ProfunctorFunctor Coyoneda where
promap f (Coyoneda l r p) = Coyoneda l r (f p)
instance ProfunctorComonad Coyoneda where
proextract (Coyoneda l r p) = dimap l r p
produplicate = Coyoneda id id
instance ProfunctorMonad Coyoneda where
proreturn = returnCoyoneda
projoin = joinCoyoneda
instance (Category p, Profunctor p) => Category (Coyoneda p) where
id = Coyoneda id id id
Coyoneda lp rp p . Coyoneda lq rq q = Coyoneda lq rp (p . rmap (lp . rq) q)
instance Strong p => Strong (Coyoneda p) where
first' = returnCoyoneda . first' . proextract
second' = returnCoyoneda . second' . proextract
instance Choice p => Choice (Coyoneda p) where
left' = returnCoyoneda . left' . proextract
right' = returnCoyoneda . right' . proextract
instance Costrong p => Costrong (Coyoneda p) where
unfirst = returnCoyoneda . unfirst . proextract
unsecond = returnCoyoneda . unsecond . proextract
instance Cochoice p => Cochoice (Coyoneda p) where
unleft = returnCoyoneda . unleft . proextract
unright = returnCoyoneda . unright . proextract
instance Closed p => Closed (Coyoneda p) where
closed = returnCoyoneda . closed . proextract
instance Mapping p => Mapping (Coyoneda p) where
map' = returnCoyoneda . map' . proextract
instance Traversing p => Traversing (Coyoneda p) where
traverse' = returnCoyoneda . traverse' . proextract
wander f = returnCoyoneda . wander f . proextract