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


-- | Utility functions for Coercible types.
--   
--   Utility functions for Coercible types.
@package coercible-utils
@version 0.0.0


-- | Primarily pulled from the package <tt><a>newtype-generics</a></tt>,
--   and based on Conor McBride's Epigram work, but generalised to work
--   over anything <a>Coercible</a>.
--   
--   <pre>
--   &gt;&gt;&gt; ala Sum foldMap [1,2,3,4 :: Int] :: Int
--   10
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; ala Endo foldMap [(+1), (+2), (subtract 1), (*2) :: Int -&gt; Int] (3 :: Int) :: Int
--   8
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; under2 Min (&lt;&gt;) 2 (1 :: Int) :: Int
--   1
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; over All not (All False) :: All
--   All {getAll = True)
--   </pre>
--   
--   <b>Note</b>: All of the functions in this module take an argument that
--   solely directs the <i>type</i> of the coercion. The value of this
--   argument is <i>ignored</i>.
module CoercibleUtils

-- | Coercive left-composition.
--   
--   <pre>
--   &gt;&gt;&gt; (All #. not) True
--   All {getAll = False}
--   </pre>
--   
--   The semantics with respect to bottoms are:
--   
--   <pre>
--   p <a>#.</a> ⊥ ≡ ⊥
--   p <a>#.</a> f ≡ p <a>.</a> f
--   </pre>
(#.) :: Coercible b c => (b -> c) -> (a -> b) -> a -> c
infixr 9 #.

-- | Coercive right-composition.
--   
--   <pre>
--   &gt;&gt;&gt; (stimes 2 .# Product) 3
--   Product {getProduct = 9}
--   </pre>
--   
--   The semantics with respect to bottoms are:
--   
--   <pre>
--   ⊥ <a>.#</a> p ≡ ⊥
--   f <a>.#</a> p ≡ p <a>.</a> f
--   </pre>
(.#) :: Coercible a b => (b -> c) -> (a -> b) -> a -> c
infixr 9 .#

-- | Reverse the type of a "packer".
--   
--   <pre>
--   &gt;&gt;&gt; op All (All True)
--   True
--   
--   &gt;&gt;&gt; op (Identity . Sum) (Identity (Sum 3))
--   3
--   </pre>
op :: Coercible a b => (a -> b) -> b -> a

-- | The workhorse of the package. Given a "packer" and a "higher order
--   function" (<i>hof</i>), it handles the packing and unpacking, and just
--   sends you back a regular old function, with the type varying based on
--   the <i>hof</i> you passed.
--   
--   The reason for the signature of the <i>hof</i> is due to <a>ala</a>
--   not caring about structure. To illustrate why this is important,
--   consider this alternative implementation of <a>under2</a>:
--   
--   <pre>
--   under2' :: (Coercible a b, Coercible a' b')
--           =&gt; (a -&gt; b) -&gt; (b -&gt; b -&gt; b') -&gt; (a -&gt; a -&gt; a')
--   under2' pa f o1 o2 = <a>ala</a> pa (\p -&gt; uncurry f . bimap p p) (o1, o2)
--   </pre>
--   
--   Being handed the "packer", the <i>hof</i> may apply it in any
--   structure of its choosing – in this case a tuple.
--   
--   <pre>
--   &gt;&gt;&gt; ala Sum foldMap [1,2,3,4 :: Int] :: Int
--   10
--   </pre>
ala :: (Coercible a b, Coercible a' b') => (a -> b) -> ((a -> b) -> c -> b') -> c -> a'

-- | The way it differs from the <a>ala</a> function in this package, is
--   that it provides an extra hook into the "packer" passed to the hof.
--   
--   However, this normally ends up being <a>id</a>, so <a>ala</a> wraps
--   this function and passes <a>id</a> as the final parameter by default.
--   If you want the convenience of being able to hook right into the
--   <i>hof</i>, you may use this function.
--   
--   <pre>
--   &gt;&gt;&gt; ala' Sum foldMap length ["hello", "world"] :: Int
--   10
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; ala' First foldMap (readMaybe @Int) ["x", "42", "1"] :: Maybe Int
--   Just 42
--   </pre>
ala' :: (Coercible a b, Coercible a' b') => (a -> b) -> ((d -> b) -> c -> b') -> (d -> a) -> c -> a'

-- | A very simple operation involving running the function <i>under</i>
--   the "packer".
--   
--   <pre>
--   &gt;&gt;&gt; under Product (stimes 3) (3 :: Int) :: Int
--   27
--   </pre>
under :: (Coercible a b, Coercible a' b') => (a -> b) -> (b -> b') -> a -> a'

-- | The opposite of <a>under</a>. I.e., take a function which works on the
--   underlying "unpacked" types, and switch it to a function that works on
--   the "packer".
--   
--   <pre>
--   &gt;&gt;&gt; over All not (All False) :: All
--   All {getAll = True}
--   </pre>
over :: (Coercible a b, Coercible a' b') => (a -> b) -> (a -> a') -> b -> b'

-- | Lower a binary function to operate on the underlying values.
--   
--   <pre>
--   &gt;&gt;&gt; under2 Any (&lt;&gt;) True False :: Bool
--   True
--   </pre>
under2 :: (Coercible a b, Coercible a' b') => (a -> b) -> (b -> b -> b') -> a -> a -> a'

-- | The opposite of <a>under2</a>.
over2 :: (Coercible a b, Coercible a' b') => (a -> b) -> (a -> a -> a') -> b -> b -> b'

-- | <a>under</a> lifted into a <a>Functor</a>.
underF :: (Coercible a b, Coercible a' b', Functor f, Functor g) => (a -> b) -> (f b -> g b') -> f a -> g a'

-- | <a>over</a> lifted into a <a>Functor</a>.
overF :: (Coercible a b, Coercible a' b', Functor f, Functor g) => (a -> b) -> (f a -> g a') -> f b -> g b'
