{-# LANGUAGE ExistentialQuantification, DefaultSignatures, UndecidableInstances #-} module Data.Profunctor.Arrow.Internal where import Data.Functor.Compose (Compose(..)) import Data.Functor.Identity (Identity(..)) import Data.Kind import Data.Profunctor import Data.Profunctor.Arrow import Data.Profunctor.Choice import Data.Profunctor.Closed import Data.Profunctor.Mapping import Data.Profunctor.Monad import Data.Profunctor.Strong import Data.Profunctor.Traversing import Data.Profunctor.Unsafe import Data.Profunctor.Yoneda import Data.Void import Prelude type family Arg (x :: * -> *) where Arg (f a) = a type family Arg1 (x :: * -> *) where Arg1 (f a b) = a type family Arg2 (x :: * -> *) where Arg2 (f a b) = b --Trans m p ~ m f => (Costar f) `Procompose` p `Procompose` (Star f) data Trans m p a b = forall x y f. m f => Trans (a -> f x) (p x y) (f y -> b) instance Profunctor (Trans m p) where dimap f g (Trans l p r) = Trans (l . f) p (g . r) lmap f (Trans l p r) = Trans (l . f) p r rmap g (Trans l p r) = Trans l p (g . r) g #. Trans l p r = Trans l p (g #. r) Trans l p r .# f = Trans (l .# f) p r instance ProfunctorFunctor (Trans m) where promap f (Trans l p r) = Trans l (f p) r type ChoiceT = Trans WithChoice type StrongT = Trans WithStrong type ClosedT = Trans WithClosed type AffineT = Trans WithAffine type TraversingT = Trans Traversable type MappingT = Trans Functor runMappingT :: Mapping q => p :-> q -> MappingT p a b -> q a b runMappingT pq (Trans l p r) = dimap l r (map' (pq p)) --prisms choice_lift :: p a b -> ChoiceT p a b choice_lift p = Trans Right p rgt' --see also PastroSum's Choice instance choice_trans :: ChoiceT p a b -> ChoiceT p (c + a) (c + b) choice_trans (Trans l p r) = Trans (either (Left . Left) (either (Left . Right) Right . l)) p (either (either Left (Right . r . Left)) (Right . r . Right)) --lenses strong_lift :: p a b -> StrongT p a b strong_lift p = Trans ((,) ()) p snd -- see also Pastro's Strong instance strong_trans :: StrongT p a b -> StrongT p (c, a) (c, b) strong_trans (Trans l p r) = Trans (\(d,s) -> ((d , fst (l s)), snd (l s))) p (\((d,c),b) -> (d,r (c,b))) --grates closed_lift :: p a b -> ClosedT p a b closed_lift p = Trans const p ($ ()) --see also Environment's Closed instance closed_trans :: ClosedT p a b -> ClosedT p (c -> a) (c -> b) closed_trans (Trans l p r) = Trans (\f (d , c) -> l (f d) c) p ((r .) . curry) --affine traversals affine :: Choice p => Strong p => p a b -> p (Affine c d a) (Affine c d b) affine = dimap unAffine Affine . right' . second' affine_lift :: p a b -> AffineT p a b affine_lift p = Trans (Affine . Right . ((,) ())) p (either absurd snd . unAffine) affine_trans :: AffineT p a b -> AffineT p (Affine c d a) (Affine c d b) affine_trans (Trans l p r) = Trans (u l) p (v r) where u :: (s -> Affine c d a) -> Affine e f s -> Affine (Either e (f,c)) (f,d) a u _ (Affine (Left e)) = Affine $ Left $ Left e u l (Affine (Right (f,s))) = Affine $ case unAffine (l s) of (Left c) -> (Left (Right (f,c))) (Right (d,a)) -> (Right ((f,d),a)) v :: (Affine c d b -> t) -> Affine (Either e (f,c)) (f,d) b -> Affine e f t v _ (Affine (Left (Left e))) = Affine $ Left e v r (Affine (Left (Right (f,c)))) = Affine $ Right (f,r $ Affine $ Left c) v r (Affine (Right ((f,d),b))) = Affine $ Right (f , r . Affine $ Right (d,b)) -- traversals traversal_lift :: p a b -> TraversingT p a b traversal_lift p = Trans Identity p runIdentity --see also TransTraversing's Traversing instance traversal_trans :: Traversable f => TraversingT p a b -> TraversingT p (f a) (f b) traversal_trans (Trans l p r) = Trans (Compose . fmap l) p (fmap r . getCompose) -- setters setter_lift :: p a b -> MappingT p a b setter_lift p = Trans Identity p runIdentity --see also TransMapping's Mapping instance setter_trans :: Functor f => MappingT p a b -> MappingT p (f a) (f b) setter_trans (Trans l p r) = Trans (Compose . fmap l) p (fmap r . getCompose) --instances class f ~ (Either (Arg f)) => WithChoice f instance WithChoice (Either c) class f ~ ((,) (Arg f)) => WithStrong f instance WithStrong ((,) c) class (f ~ ((->) (Arg f))) => WithClosed f instance WithClosed ((->) c) newtype Affine a b c = Affine { unAffine :: a + (b , c) } class f ~ Affine (Arg1 f) (Arg2 f) => WithAffine f instance WithAffine (Affine c d) instance Choice (ChoiceT p) where right' = choice_trans instance Strong (StrongT p) where second' = strong_trans instance Closed (ClosedT p) where closed = closed_trans instance Choice (AffineT p) where right' = dimap (Affine . either (Left . id) (Right . ((,) ()))) (either Left (Right . snd) . unAffine) . affine_trans instance Strong (AffineT p) where second' = dimap (Affine . Right) (either absurd id . unAffine) . affine_trans instance Strong (TraversingT p) where second' = traverse' instance Choice (TraversingT p) where right' = traverse' instance Traversing (TraversingT p) where traverse' = traversal_trans instance Strong (MappingT p) where second' = map' instance Choice (MappingT p) where right' = map' instance Closed (MappingT p) where closed = map' instance Traversing (MappingT p) where traverse' = map' instance Mapping (MappingT p) where map' = setter_trans