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


-- | Haskell 98 compatible comonads
--   
--   Haskell 98 compatible comonads
@package comonad
@version 3.0.1.1


module Control.Comonad

-- | There are two ways to define a comonad:
--   
--   I. Provide definitions for <a>extract</a> and <a>extend</a> satisfying
--   these laws:
--   
--   <pre>
--   extend extract      = id
--   extract . extend f  = f
--   extend f . extend g = extend (f . extend g)
--   </pre>
--   
--   In this case, you may simply set <a>fmap</a> = <a>liftW</a>.
--   
--   These laws are directly analogous to the laws for monads and perhaps
--   can be made clearer by viewing them as laws stating that Cokleisli
--   composition must be associative, and has extract for a unit:
--   
--   <pre>
--   f =&gt;= extract   = f
--   extract =&gt;= f   = f
--   (f =&gt;= g) =&gt;= h = f =&gt;= (g =&gt;= h)
--   </pre>
--   
--   II. Alternately, you may choose to provide definitions for
--   <a>fmap</a>, <a>extract</a>, and <a>duplicate</a> satisfying these
--   laws:
--   
--   <pre>
--   extract . duplicate      = id
--   fmap extract . duplicate = id
--   duplicate . duplicate    = fmap duplicate . duplicate
--   </pre>
--   
--   In this case you may not rely on the ability to define <a>fmap</a> in
--   terms of <a>liftW</a>.
--   
--   You may of course, choose to define both <a>duplicate</a> <i>and</i>
--   <a>extend</a>. In that case you must also satisfy these laws:
--   
--   <pre>
--   extend f  = fmap f . duplicate
--   duplicate = extend id
--   fmap f    = extend (f . extract)
--   </pre>
--   
--   These are the default definitions of <a>extend</a> and
--   <a>duplicate</a> and the definition of <a>liftW</a> respectively.
class Functor w => Comonad w where duplicate = extend id extend f = fmap f . duplicate
extract :: Comonad w => w a -> a
duplicate :: Comonad w => w a -> w (w a)
extend :: Comonad w => (w a -> b) -> w a -> w b

-- | A suitable default definition for <a>fmap</a> for a <a>Comonad</a>.
--   Promotes a function to a comonad.
--   
--   <pre>
--   fmap f = liftW f = extend (f . extract)
--   </pre>
liftW :: Comonad w => (a -> b) -> w a -> w b

-- | Comonadic fixed point à la Menendez
wfix :: Comonad w => w (w a -> a) -> a

-- | Comonadic fixed point à la Orchard
cfix :: Comonad w => (w a -> a) -> w a

-- | Left-to-right Cokleisli composition
(=>=) :: Comonad w => (w a -> b) -> (w b -> c) -> w a -> c

-- | Right-to-left Cokleisli composition
(=<=) :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c

-- | <a>extend</a> in operator form
(<<=) :: Comonad w => (w a -> b) -> w a -> w b

-- | <a>extend</a> with the arguments swapped. Dual to <a>&gt;&gt;=</a> for
--   a <a>Monad</a>.
(=>>) :: Comonad w => w a -> (w a -> b) -> w b

-- | A <tt>ComonadApply w</tt> is a strong lax symmetric semi-monoidal
--   comonad on the category <tt>Hask</tt> of Haskell types.
--   
--   That it to say that <tt>w</tt> is a strong lax symmetric semi-monoidal
--   functor on Hask, where both extract and duplicate are symmetric
--   monoidal natural transformations.
--   
--   Laws:
--   
--   <pre>
--   (.) &lt;$&gt; u &lt;@&gt; v &lt;@&gt; w = u &lt;@&gt; (v &lt;@&gt; w)
--   extract p (extract q) = extract (p &lt;@&gt; q)
--   duplicate (p &lt;*&gt; q) = (\r s -&gt; fmap (r &lt;@&gt; s)) &lt;@&gt; duplicate q &lt;*&gt; duplicate q
--   </pre>
--   
--   If our type is both a ComonadApply and Applicative we further require
--   
--   <pre>
--   (&lt;*&gt;) = (&lt;@&gt;)
--   </pre>
--   
--   Finally, if you choose to define (<a>&lt;@</a>) and (<a>@&gt;</a>),
--   the results of your definitions should match the following laws:
--   
--   <pre>
--   a @&gt; b = const id &lt;$&gt; a &lt;@&gt; b
--   a &lt;@ b = const &lt;$&gt; a &lt;@&gt; b
--   </pre>
class Comonad w => ComonadApply w where a @> b = const id <$> a <@> b a <@ b = const <$> a <@> b
(<@>) :: ComonadApply w => w (a -> b) -> w a -> w b
(@>) :: ComonadApply w => w a -> w b -> w b
(<@) :: ComonadApply w => w a -> w b -> w a

-- | A variant of <a>&lt;@&gt;</a> with the arguments reversed.
(<@@>) :: ComonadApply w => w a -> w (a -> b) -> w b

-- | Lift a binary function into a comonad with zipping
liftW2 :: ComonadApply w => (a -> b -> c) -> w a -> w b -> w c

-- | Lift a ternary function into a comonad with zipping
liftW3 :: ComonadApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d

-- | The <a>Cokleisli</a> <a>Arrow</a>s of a given <a>Comonad</a>
newtype Cokleisli w a b
Cokleisli :: (w a -> b) -> Cokleisli w a b
runCokleisli :: Cokleisli w a b -> w a -> b

-- | The <a>Functor</a> class is used for types that can be mapped over.
--   Instances of <a>Functor</a> should satisfy the following laws:
--   
--   <pre>
--   fmap id  ==  id
--   fmap (f . g)  ==  fmap f . fmap g
--   </pre>
--   
--   The instances of <a>Functor</a> for lists, <a>Maybe</a> and <a>IO</a>
--   satisfy these laws.
class Functor (f :: * -> *)
fmap :: Functor f => (a -> b) -> f a -> f b
(<$) :: Functor f => a -> f b -> f a

-- | An infix synonym for <a>fmap</a>.
(<$>) :: Functor f => (a -> b) -> f a -> f b

-- | Replace the contents of a functor uniformly with a constant value.
($>) :: Functor f => f a -> b -> f b
instance Monad (Cokleisli w a)
instance Applicative (Cokleisli w a)
instance Functor (Cokleisli w a)
instance ComonadApply w => ArrowLoop (Cokleisli w)
instance Comonad w => ArrowChoice (Cokleisli w)
instance Comonad w => ArrowApply (Cokleisli w)
instance Comonad w => Arrow (Cokleisli w)
instance Comonad w => Category (Cokleisli w)
instance Typeable1 w => Typeable2 (Cokleisli w)
instance ComonadApply Tree
instance ComonadApply w => ComonadApply (IdentityT w)
instance ComonadApply Identity
instance Monoid m => ComonadApply ((->) m)
instance ComonadApply NonEmpty
instance Semigroup m => ComonadApply ((,) m)
instance Comonad NonEmpty
instance Comonad Tree
instance Comonad w => Comonad (IdentityT w)
instance Comonad Identity
instance Monoid m => Comonad ((->) m)
instance Comonad ((,) e)
