{-# LANGUAGE CPP #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Profunctor.Unsafe
(
Profunctor(..)
) where
import Control.Arrow
import Control.Category
import Control.Comonad (Cokleisli(..))
import Control.Monad (liftM)
import Data.Bifunctor.Biff (Biff(..))
import Data.Bifunctor.Clown (Clown(..))
import Data.Bifunctor.Joker (Joker(..))
import Data.Bifunctor.Product (Product(..))
import Data.Bifunctor.Sum (Sum(..))
import Data.Bifunctor.Tannen (Tannen(..))
import Data.Coerce (Coercible, coerce)
#if __GLASGOW_HASKELL__ < 710
import Data.Functor
#endif
import Data.Functor.Contravariant (Contravariant(..))
import Data.Tagged
import Prelude hiding (id,(.))
infixr 9 #.
infixl 8 .#
class Profunctor p where
dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
dimap f g = lmap f . rmap g
{-# INLINE dimap #-}
lmap :: (a -> b) -> p b c -> p a c
lmap f = dimap f id
{-# INLINE lmap #-}
rmap :: (b -> c) -> p a b -> p a c
rmap = dimap id
{-# INLINE rmap #-}
(#.) :: forall a b c q. Coercible c b => q b c -> p a b -> p a c
(#.) = \_ -> \p -> p `seq` rmap (coerce (id :: c -> c) :: b -> c) p
{-# INLINE (#.) #-}
(.#) :: forall a b c q. Coercible b a => p b c -> q a b -> p a c
(.#) = \p -> p `seq` \_ -> lmap (coerce (id :: b -> b) :: a -> b) p
{-# INLINE (.#) #-}
{-# MINIMAL dimap | (lmap, rmap) #-}
instance Profunctor (->) where
dimap ab cd bc = cd . bc . ab
{-# INLINE dimap #-}
lmap = flip (.)
{-# INLINE lmap #-}
rmap = (.)
{-# INLINE rmap #-}
(#.) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
(.#) pbc _ = coerce pbc
{-# INLINE (#.) #-}
{-# INLINE (.#) #-}
instance Profunctor Tagged where
dimap _ f (Tagged s) = Tagged (f s)
{-# INLINE dimap #-}
lmap _ = retag
{-# INLINE lmap #-}
rmap = fmap
{-# INLINE rmap #-}
(#.) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
{-# INLINE (#.) #-}
Tagged s .# _ = Tagged s
{-# INLINE (.#) #-}
instance Monad m => Profunctor (Kleisli m) where
dimap f g (Kleisli h) = Kleisli (liftM g . h . f)
{-# INLINE dimap #-}
lmap k (Kleisli f) = Kleisli (f . k)
{-# INLINE lmap #-}
rmap k (Kleisli f) = Kleisli (liftM k . f)
{-# INLINE rmap #-}
(.#) pbc _ = coerce pbc
{-# INLINE (.#) #-}
instance Functor w => Profunctor (Cokleisli w) where
dimap f g (Cokleisli h) = Cokleisli (g . h . fmap f)
{-# INLINE dimap #-}
lmap k (Cokleisli f) = Cokleisli (f . fmap k)
{-# INLINE lmap #-}
rmap k (Cokleisli f) = Cokleisli (k . f)
{-# INLINE rmap #-}
(#.) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
{-# INLINE (#.) #-}
instance Contravariant f => Profunctor (Clown f) where
lmap f (Clown fa) = Clown (contramap f fa)
{-# INLINE lmap #-}
rmap _ (Clown fa) = Clown fa
{-# INLINE rmap #-}
dimap f _ (Clown fa) = Clown (contramap f fa)
{-# INLINE dimap #-}
instance Functor f => Profunctor (Joker f) where
lmap _ (Joker fb) = Joker fb
{-# INLINE lmap #-}
rmap g (Joker fb) = Joker (fmap g fb)
{-# INLINE rmap #-}
dimap _ g (Joker fb) = Joker (fmap g fb)
{-# INLINE dimap #-}
instance (Profunctor p, Functor f, Functor g) => Profunctor (Biff p f g) where
lmap f (Biff p) = Biff (lmap (fmap f) p)
rmap g (Biff p) = Biff (rmap (fmap g) p)
dimap f g (Biff p) = Biff (dimap (fmap f) (fmap g) p)
instance (Profunctor p, Profunctor q) => Profunctor (Product p q) where
lmap f (Pair p q) = Pair (lmap f p) (lmap f q)
{-# INLINE lmap #-}
rmap g (Pair p q) = Pair (rmap g p) (rmap g q)
{-# INLINE rmap #-}
dimap f g (Pair p q) = Pair (dimap f g p) (dimap f g q)
{-# INLINE dimap #-}
(#.) f (Pair p q) = Pair (f #. p) (f #. q)
{-# INLINE (#.) #-}
(.#) (Pair p q) f = Pair (p .# f) (q .# f)
{-# INLINE (.#) #-}
instance (Profunctor p, Profunctor q) => Profunctor (Sum p q) where
lmap f (L2 x) = L2 (lmap f x)
lmap f (R2 y) = R2 (lmap f y)
{-# INLINE lmap #-}
rmap g (L2 x) = L2 (rmap g x)
rmap g (R2 y) = R2 (rmap g y)
{-# INLINE rmap #-}
dimap f g (L2 x) = L2 (dimap f g x)
dimap f g (R2 y) = R2 (dimap f g y)
{-# INLINE dimap #-}
f #. L2 x = L2 (f #. x)
f #. R2 y = R2 (f #. y)
{-# INLINE (#.) #-}
L2 x .# f = L2 (x .# f)
R2 y .# f = R2 (y .# f)
{-# INLINE (.#) #-}
instance (Functor f, Profunctor p) => Profunctor (Tannen f p) where
lmap f (Tannen h) = Tannen (lmap f <$> h)
{-# INLINE lmap #-}
rmap g (Tannen h) = Tannen (rmap g <$> h)
{-# INLINE rmap #-}
dimap f g (Tannen h) = Tannen (dimap f g <$> h)
{-# INLINE dimap #-}
(#.) f (Tannen h) = Tannen ((f #.) <$> h)
{-# INLINE (#.) #-}
(.#) (Tannen h) f = Tannen ((.# f) <$> h)
{-# INLINE (.#) #-}