module Data.Profunctor.Misc where
import Control.Arrow ((|||),(&&&))
import Control.Category
import Control.Comonad (Comonad(..))
import Control.Monad (join)
import Data.Bifunctor
import Data.Functor.Contravariant
import Data.Functor.Contravariant.Divisible
import Data.Profunctor
import Data.Profunctor.Rep
import Data.Profunctor.Sieve
import Data.Void
import Prelude hiding ((.), id)
infixr 5 +
type (+) = Either
rgt :: (a -> b) -> a + b -> b
rgt f = either f id
rgt' :: Void + b -> b
rgt' = rgt absurd
lft :: (b -> a) -> a + b -> a
lft f = either id f
lft' :: a + Void -> a
lft' = lft absurd
dup :: a -> (a , a)
dup = join (,)
dedup :: (a + a) -> a
dedup = join either id
swp :: (a1 , a2) -> (a2 , a1)
swp = snd &&& fst
swp' :: (a1 + a2) -> (a2 + a1)
swp' = Right ||| Left
assocl :: (a , (b , c)) -> ((a , b) , c)
assocl (a, (b, c)) = ((a, b), c)
assocr :: ((a , b) , c) -> (a , (b , c))
assocr ((a, b), c) = (a, (b, c))
assocl' :: (a + (b + c)) -> ((a + b) + c)
assocl' (Left a) = Left (Left a)
assocl' (Right (Left b)) = Left (Right b)
assocl' (Right (Right c)) = Right c
assocr' :: ((a + b) + c) -> (a + (b + c))
assocr' (Left (Left a)) = Left a
assocr' (Left (Right b)) = Right (Left b)
assocr' (Right c) = Right (Right c)
eval :: (a , a -> b) -> b
eval = uncurry $ flip id
apply :: (b -> a , b) -> a
apply = uncurry id
coeval :: b -> (b -> a) + a -> a
coeval b = either ($ b) id
branch :: (a -> Bool) -> b -> c -> a -> b + c
branch f y z x = if f x then Right z else Left y
branch' :: (a -> Bool) -> a -> a + a
branch' f x = branch f x x x
fstrong :: Functor f => f a -> b -> f (a , b)
fstrong f b = fmap (,b) f
fchoice :: Traversable f => f (a + b) -> (f a) + b
fchoice = swp' . traverse swp'
pfirst :: Strong p => p a b -> p (a , c) (b , c)
pfirst = first'
psecond :: Strong p => p a b -> p (c , a) (c , b)
psecond = second'
pleft :: Choice p => p a b -> p (a + c) (b + c)
pleft = left'
pright :: Choice p => p a b -> p (c + a) (c + b)
pright = right'
pcurry :: Closed p => p (a , b) c -> p a (b -> c)
pcurry = curry'
puncurry :: Strong p => p a (b -> c) -> p (a , b) c
puncurry = uncurry'
peval :: Strong p => p a (a -> b) -> p a b
peval = rmap eval . pull
constl :: Profunctor p => b -> p b c -> p a c
constl = lmap . const
constr :: Profunctor p => c -> p a b -> p a c
constr = rmap . const
shiftl :: Profunctor p => p (a + b) c -> p b (c + d)
shiftl = dimap Right Left
shiftr :: Profunctor p => p b (c , d) -> p (a , b) c
shiftr = dimap snd fst
coercer :: Profunctor p => Contravariant (p a) => p a c -> p a d
coercer = rmap absurd . contramap absurd
coercer' :: Representable p => Contravariant (Rep p) => p a b -> p a c
coercer' = lift (phantom .)
coercel :: Profunctor p => Bifunctor p => p a c -> p b c
coercel = first absurd . lmap absurd
coercel' :: Corepresentable p => Contravariant (Corep p) => p a b -> p c b
coercel' = lower (. phantom)
strong :: Strong p => ((a , b) -> c) -> p a b -> p a c
strong f = dimap dup f . psecond
costrong :: Costrong p => ((a , b) -> c) -> p c a -> p b a
costrong f = unsecond . dimap f dup
choice :: Choice p => (c -> (a + b)) -> p b a -> p c a
choice f = dimap f dedup . pright
cochoice :: Cochoice p => (c -> (a + b)) -> p a c -> p a b
cochoice f = unright . dimap dedup f
pull :: Strong p => p a b -> p a (a , b)
pull = lmap dup . psecond
parr :: Category p => Profunctor p => (a -> b) -> p a b
parr f = dimap id f id
punarr :: Comonad w => Sieve p w => p a b -> a -> b
punarr = (extract .) . sieve
returnP :: Category p => Profunctor p => p a a
returnP = parr id
ex1 :: Category p => Profunctor p => p (a , b) b
ex1 = parr snd
ex2 :: Category p => Profunctor p => p (a , b) a
ex2 = parr fst
inl :: Category p => Profunctor p => p a (a + b)
inl = parr Left
inr :: Category p => Profunctor p => p b (a + b)
inr = parr Right
braid :: Category p => Profunctor p => p (a , b) (b , a)
braid = parr swp
braid' :: Category p => Profunctor p => p (a + b) (b + a)
braid' = parr swp'
lift :: Representable p => ((a -> Rep p b) -> s -> Rep p t) -> p a b -> p s t
lift f = tabulate . f . sieve
lower :: Corepresentable p => ((Corep p a -> b) -> Corep p s -> t) -> p a b -> p s t
lower f = cotabulate . f . cosieve
infixr 3 @@@
(@@@) :: Profunctor p => (forall x. Applicative (p x)) => p a1 b1 -> p a2 b2 -> p (a1 , a2) (b1 , b2)
f @@@ g = pappend f g
pappend :: Profunctor p => (forall x. Applicative (p x)) => p a1 b1 -> p a2 b2 -> p (a1 , a2) (b1 , b2)
pappend f g = dimap fst (,) f <*> lmap snd g
pdivide :: Profunctor p => (forall x. Applicative (p x)) => (a -> (a1 , a2)) -> p a1 b -> p a2 b -> p a b
pdivide f x y = dimap f fst $ pappend x y
pdivided :: Profunctor p => (forall x. Applicative (p x)) => p a1 b -> p a2 b -> p (a1 , a2) b
pdivided = pdivide id
papply :: Profunctor p => (forall x. Applicative (p x)) => p a (b -> c) -> p a b -> p a c
papply f x = dimap dup apply (f @@@ x)
pliftA2 :: Profunctor p => (forall x. Applicative (p x)) => ((b1 , b2) -> b) -> p a b1 -> p a b2 -> p a b
pliftA2 f x y = dimap dup f $ pappend x y
ppure :: Profunctor p => (forall x. Applicative (p x)) => b -> p a b
ppure b = dimap (const ()) (const b) $ pure ()
pabsurd :: Profunctor p => (forall x. Divisible (p x)) => p Void a
pabsurd = rmap absurd $ conquer