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


-- | A typeclass and set of functions for working with newtypes.
--   
--   Per Conor McBride, the Newtype typeclass represents the packing and
--   unpacking of a newtype, and allows you to operatate under that newtype
--   with functions such as ala.
@package newtype
@version 0.2


-- | The <a>Newtype</a> typeclass and related functions: <a>op</a>,
--   <a>ala</a>, <a>ala'</a>, <a>under</a>. Primarly pulled from Conor
--   McBride's Epigram work. Some examples:
--   
--   <pre>
--   ala Sum foldMap [1,2,3,4] -- foldMaps the list ala the Sum newtype. This results in 10.
--   </pre>
--   
--   <pre>
--   ala Product foldMap [1,2,3,4] -- foldMaps the list ala the Product newtype. This results in 24.
--   </pre>
--   
--   <pre>
--   ala Endo foldMap [(+1), (+2), (subtract 1), (*2)] 3 -- foldMaps the list ala the Endo newtype. This results in 8.
--   </pre>
--   
--   NB: <a>foldMap</a> is a generalized <tt>mconcatMap</tt> which is a
--   generalized <tt>concatMap</tt>.
--   
--   This package includes <a>Newtype</a> instances for all the
--   (non-GHC/foreign) newtypes in base (as seen in the examples). However,
--   there are neat things you can do with this with <i>any</i> newtype and
--   you should definitely define your own <a>Newtype</a> instances for the
--   power of this library. For example, see <tt>ala Cont traverse</tt>,
--   with the proper <a>Newtype</a> instance for Cont.
module Control.Newtype

-- | Given a newtype <tt>n</tt>, we will always have the same unwrapped
--   type <tt>o</tt>, meaning we can represent this with a fundep <tt>n
--   -&gt; o</tt>.
--   
--   Any instance of this class just needs to let <tt>pack</tt> equal to
--   the newtype's constructor, and let <tt>unpack</tt> destruct the
--   newtype with pattern matching.
class Newtype n o | n -> o
pack :: Newtype n o => o -> n
unpack :: Newtype n o => n -> o

-- | This function serves two purposes:
--   
--   <ol>
--   <li>Giving you the unpack of a newtype without you needing to remember
--   the name.</li>
--   <li>Showing that the first parameter is <i>completely ignored</i> on
--   the value level, meaning the only reason you pass in the constructor
--   is to provide type information. Typeclasses sure are neat.</li>
--   </ol>
op :: Newtype n o => (o -> n) -> n -> o

-- | The workhorse of the package. Given a pack and a "higher order
--   function", it handles the packing and unpacking, and just sends you
--   back a regular old function, with the type varying based on the hof
--   you passed.
--   
--   The reason for the signature of the hof is due to <a>ala</a> not
--   caring about structure. To illustrate why this is important, another
--   function in this package is <a>under</a>. It is not extremely useful;
--   <tt>under2</tt> might be more useful (with e.g., <tt>mappend</tt>),
--   but then we already digging the trench of "What about <tt>under3</tt>?
--   <tt>under4</tt>?". The solution utilized here is to just hand off the
--   "packer" to the hof. That way your structure can be imposed in the
--   hof, whatever you may want it to be (e.g., List, Traversable).
ala :: (Newtype n o, Newtype n' o') => (o -> n) -> ((o -> n) -> b -> n') -> (b -> o')

-- | This is the original function seen in Conor McBride's work. 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 <tt>id</tt>, so <a>ala</a> wraps this
--   function and passes <tt>id</tt> as the final parameter by default. If
--   you want the convenience of being able to hook right into the hof, you
--   may use this function.
ala' :: (Newtype n o, Newtype n' o') => (o -> n) -> ((a -> n) -> b -> n') -> (a -> o) -> (b -> o')

-- | A very simple operation involving running the function 'under' the
--   newtype. Suffers from the problems mentioned in the <a>ala</a>
--   function's documentation.
under :: (Newtype n o, Newtype n' o') => (o -> n) -> (n -> n') -> (o -> o')

-- | The opposite of <a>under</a>. I.e., take a function which works on the
--   underlying types, and switch it to a function that works on the
--   newtypes.
over :: (Newtype n o, Newtype n' o') => (o -> n) -> (o -> o') -> (n -> n')

-- | <a>under</a> lifted into a Functor.
underF :: (Newtype n o, Newtype n' o', Functor f) => (o -> n) -> (f n -> f n') -> (f o -> f o')

-- | <a>over</a> lifted into a Functor.
overF :: (Newtype n o, Newtype n' o', Functor f) => (o -> n) -> (f o -> f o') -> (f n -> f n')
instance Control.Newtype.Newtype Data.Monoid.All GHC.Types.Bool
instance Control.Newtype.Newtype Data.Monoid.Any GHC.Types.Bool
instance Control.Newtype.Newtype (Data.Monoid.Sum a) a
instance Control.Newtype.Newtype (Data.Monoid.Product a) a
instance Control.Newtype.Newtype (Control.Arrow.Kleisli m a b) (a -> m b)
instance Control.Newtype.Newtype (Control.Applicative.WrappedMonad m a) (m a)
instance Control.Newtype.Newtype (Control.Applicative.WrappedArrow a b c) (a b c)
instance Control.Newtype.Newtype (Control.Applicative.ZipList a) [a]
instance Control.Newtype.Newtype (Data.Functor.Const.Const a x) a
instance Control.Newtype.Newtype (Data.Monoid.Endo a) (a -> a)
instance Control.Newtype.Newtype (Data.Monoid.First a) (GHC.Base.Maybe a)
instance Control.Newtype.Newtype (Data.Monoid.Last a) (GHC.Base.Maybe a)
instance Control.Arrow.ArrowApply a => Control.Newtype.Newtype (Control.Arrow.ArrowMonad a b) (a () b)
