-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Haskell 98 Profunctors
--   
--   Haskell 98 Profunctors
@package profunctors
@version 3.3


-- | For a good explanation of profunctors in Haskell see Dan Piponi's
--   article:
--   
--   <a>http://blog.sigfpe.com/2011/07/profunctors-in-haskell.html</a>
--   
--   This module includes <i>unsafe</i> composition operators that are
--   useful in practice when it comes to generating optimal core in GHC.
--   
--   If you import this module you are taking upon yourself the obligation
--   that you will only call the operators with <tt>#</tt> in their names
--   with functions that are operationally identity such as
--   <tt>newtype</tt> constructors or the field accessor of a
--   <tt>newtype</tt>.
--   
--   If you are ever in doubt, use <a>rmap</a> or <a>lmap</a>.
module Data.Profunctor.Unsafe

-- | Formally, the class <a>Profunctor</a> represents a profunctor from
--   <tt>Hask</tt> -&gt; <tt>Hask</tt>.
--   
--   Intuitively it is a bifunctor where the first argument is
--   contravariant and the second argument is covariant.
--   
--   You can define a <a>Profunctor</a> by either defining <a>dimap</a> or
--   by defining both <a>lmap</a> and <a>rmap</a>.
--   
--   If you supply <a>dimap</a>, you should ensure that:
--   
--   <pre>
--   <a>dimap</a> <a>id</a> <a>id</a> ≡ <a>id</a>
--   </pre>
--   
--   If you supply <a>lmap</a> and <a>rmap</a>, ensure:
--   
--   <pre>
--   <a>lmap</a> <a>id</a> ≡ <a>id</a>
--   <a>rmap</a> <a>id</a> ≡ <a>id</a>
--   </pre>
--   
--   If you supply both, you should also ensure:
--   
--   <pre>
--   <a>dimap</a> f g ≡ <a>lmap</a> f <a>.</a> <a>rmap</a> g
--   </pre>
--   
--   These ensure by parametricity:
--   
--   <pre>
--   <a>dimap</a> (f <a>.</a> g) (h <a>.</a> i) ≡ <a>dimap</a> g h <a>.</a> <a>dimap</a> f i
--   <a>lmap</a> (f <a>.</a> g) ≡ <a>lmap</a> g <a>.</a> <a>lmap</a> f
--   <a>rmap</a> (f <a>.</a> g) ≡ <a>rmap</a> f <a>.</a> <a>rmap</a> g
--   </pre>
class Profunctor p where dimap f g = lmap f . rmap g lmap f = dimap f id rmap = dimap id #. = \ f -> \ p -> p `seq` rmap f p .# = \ p -> p `seq` \ f -> lmap f p
dimap :: Profunctor p => (a -> b) -> (c -> d) -> p b c -> p a d
lmap :: Profunctor p => (a -> b) -> p b c -> p a c
rmap :: Profunctor p => (b -> c) -> p a b -> p a c
(#.) :: Profunctor p => (b -> c) -> p a b -> p a c
(.#) :: Profunctor p => p b c -> (a -> b) -> p a c
instance Functor w => Profunctor (Cokleisli w)
instance Monad m => Profunctor (Kleisli m)
instance Profunctor (Tagged *)
instance Profunctor (->)


-- | For a good explanation of profunctors in Haskell see Dan Piponi's
--   article:
--   
--   <a>http://blog.sigfpe.com/2011/07/profunctors-in-haskell.html</a>
--   
--   For more information on strength and costrength, see:
--   
--   <a>http://comonad.com/reader/2008/deriving-strength-from-laziness/</a>
module Data.Profunctor

-- | Formally, the class <a>Profunctor</a> represents a profunctor from
--   <tt>Hask</tt> -&gt; <tt>Hask</tt>.
--   
--   Intuitively it is a bifunctor where the first argument is
--   contravariant and the second argument is covariant.
--   
--   You can define a <a>Profunctor</a> by either defining <a>dimap</a> or
--   by defining both <a>lmap</a> and <a>rmap</a>.
--   
--   If you supply <a>dimap</a>, you should ensure that:
--   
--   <pre>
--   <a>dimap</a> <a>id</a> <a>id</a> ≡ <a>id</a>
--   </pre>
--   
--   If you supply <a>lmap</a> and <a>rmap</a>, ensure:
--   
--   <pre>
--   <a>lmap</a> <a>id</a> ≡ <a>id</a>
--   <a>rmap</a> <a>id</a> ≡ <a>id</a>
--   </pre>
--   
--   If you supply both, you should also ensure:
--   
--   <pre>
--   <a>dimap</a> f g ≡ <a>lmap</a> f <a>.</a> <a>rmap</a> g
--   </pre>
--   
--   These ensure by parametricity:
--   
--   <pre>
--   <a>dimap</a> (f <a>.</a> g) (h <a>.</a> i) ≡ <a>dimap</a> g h <a>.</a> <a>dimap</a> f i
--   <a>lmap</a> (f <a>.</a> g) ≡ <a>lmap</a> g <a>.</a> <a>lmap</a> f
--   <a>rmap</a> (f <a>.</a> g) ≡ <a>rmap</a> f <a>.</a> <a>rmap</a> g
--   </pre>
class Profunctor p where dimap f g = lmap f . rmap g lmap f = dimap f id rmap = dimap id #. = \ f -> \ p -> p `seq` rmap f p .# = \ p -> p `seq` \ f -> lmap f p
dimap :: Profunctor p => (a -> b) -> (c -> d) -> p b c -> p a d
lmap :: Profunctor p => (a -> b) -> p b c -> p a c
rmap :: Profunctor p => (b -> c) -> p a b -> p a c

-- | Generalizing upstar of a strong <a>Functor</a>
--   
--   Minimal complete definition: <a>first'</a> or <a>second'</a>
--   
--   <i>Note:</i> Every <a>Functor</a> in Haskell is strong.
class Profunctor p => Strong p where first' = dimap swap swap . second' second' = dimap swap swap . first'
first' :: Strong p => p a b -> p (a, c) (b, c)
second' :: Strong p => p a b -> p (c, a) (c, b)

-- | The generalization of <a>DownStar</a> of a "costrong" <a>Functor</a>
--   
--   Minimal complete definition: <a>left'</a> or <a>right'</a>
--   
--   <i>Note:</i> We use <a>traverse</a> and <a>extract</a> as approximate
--   costrength as needed.
class Profunctor p => Choice p where left' = dimap (either Right Left) (either Right Left) . right' right' = dimap (either Right Left) (either Right Left) . left'
left' :: Choice p => p a b -> p (Either a c) (Either b c)
right' :: Choice p => p a b -> p (Either c a) (Either c b)

-- | Lift a <a>Functor</a> into a <a>Profunctor</a> (forwards).
newtype UpStar f d c
UpStar :: (d -> f c) -> UpStar f d c
runUpStar :: UpStar f d c -> d -> f c

-- | Lift a <a>Functor</a> into a <a>Profunctor</a> (backwards).
newtype DownStar f d c
DownStar :: (f d -> c) -> DownStar f d c
runDownStar :: DownStar f d c -> f d -> c

-- | Wrap an arrow for use as a <a>Profunctor</a>.
newtype WrappedArrow p a b
WrapArrow :: p a b -> WrappedArrow p a b
unwrapArrow :: WrappedArrow p a b -> p a b
newtype Forget r a b
Forget :: (a -> r) -> Forget r a b
runForget :: Forget r a b -> a -> r
instance Monoid r => Choice (Forget r)
instance ArrowChoice p => Choice (WrappedArrow p)
instance Choice (Tagged *)
instance Traversable w => Choice (DownStar w)
instance Comonad w => Choice (Cokleisli w)
instance Applicative f => Choice (UpStar f)
instance Monad m => Choice (Kleisli m)
instance Choice (->)
instance Strong (Forget r)
instance Arrow p => Strong (WrappedArrow p)
instance Functor m => Strong (UpStar m)
instance Monad m => Strong (Kleisli m)
instance Strong (->)
instance Traversable (Forget r a)
instance Foldable (Forget r a)
instance Functor (Forget r a)
instance Profunctor (Forget r)
instance Arrow p => Profunctor (WrappedArrow p)
instance ArrowLoop p => ArrowLoop (WrappedArrow p)
instance ArrowApply p => ArrowApply (WrappedArrow p)
instance ArrowChoice p => ArrowChoice (WrappedArrow p)
instance ArrowZero p => ArrowZero (WrappedArrow p)
instance Arrow p => Arrow (WrappedArrow p)
instance Category p => Category (WrappedArrow p)
instance Functor (DownStar f a)
instance Functor f => Profunctor (DownStar f)
instance Functor f => Functor (UpStar f a)
instance Functor f => Profunctor (UpStar f)
