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


-- | A typeclass and set of functions for working with newtypes, with generics support.
--   
--   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. Generics support was added in version 0.4,
--   making this package a full replacement for the original newtype
--   package, and a better alternative to newtype-th.
@package newtype-generics
@version 0.5


-- | 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. You can easily
--   define new instances for your newtypes with the help of GHC.Generics
--   
--   <pre>
--   import GHC.Generics
--   
--   (...)
--   newtype Example = Example Int 
--     deriving (Generic)
--   
--   instance Newtype Example
--   </pre>
--   
--   This avoids the use of Template Haskell (TH) to get new instances.
module Control.Newtype

-- | As long as the type <tt>n</tt> is an instance of Generic, you can
--   create an instance with just <tt>instance Newtype n</tt>
class Newtype n where type O n :: * type O n = GO (Rep n) pack = to . gpack unpack = gunpack . from where {
    type family O n :: *;
    type O n = GO (Rep n);
}
pack :: Newtype n => O n -> n
pack :: (Newtype n, Generic n, GNewtype (Rep n), O n ~ GO (Rep n)) => O n -> n
unpack :: Newtype n => n -> O n
unpack :: (Newtype n, Generic n, GNewtype (Rep n), O n ~ GO (Rep n)) => n -> O n

-- | 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) => (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, Newtype n', o' ~ O n', o ~ O n) => (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, Newtype n', o' ~ O n', o ~ O n) => (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, Newtype n', o' ~ O n', o ~ O n) => (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, Newtype n', o' ~ O n', o ~ O n) => (o -> n) -> (o -> o') -> (n -> n')

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

-- | <a>over</a> lifted into a Functor.
overF :: (Newtype n, Newtype n', o' ~ O n', o ~ O n, Functor f, Functor g) => (o -> n) -> (f o -> g o') -> (f n -> g n')
instance Control.Newtype.GNewtype (GHC.Generics.D1 d (GHC.Generics.C1 c (GHC.Generics.S1 s (GHC.Generics.K1 i a))))
instance Control.Newtype.Newtype Data.Monoid.All
instance Control.Newtype.Newtype Data.Monoid.Any
instance Control.Newtype.Newtype (Data.Monoid.Sum a)
instance Control.Newtype.Newtype (Data.Monoid.Product a)
instance Control.Newtype.Newtype (Data.Monoid.First a)
instance Control.Newtype.Newtype (Data.Monoid.Last a)
instance Control.Newtype.Newtype (Data.Monoid.Endo a)
instance Control.Newtype.Newtype (Control.Applicative.ZipList a)
instance Control.Newtype.Newtype (Data.Functor.Const.Const a x)
instance Control.Newtype.Newtype (Control.Arrow.Kleisli m a b)
instance Control.Newtype.Newtype (Control.Applicative.WrappedMonad m a)
instance Control.Newtype.Newtype (Control.Applicative.WrappedArrow a b c)
instance Control.Newtype.Newtype (Control.Arrow.ArrowMonad a b)
