{-# LANGUAGE FlexibleContexts #-}

-- | Generic deriving for standard classes in base
--
-- === Warning
--
-- This is an internal module: it is not subject to any versioning policy,
-- breaking changes can happen at any time.
--
-- If something here seems useful, please report it or create a pull request to
-- export it from an external module.

module Generic.Data.Internal.Prelude where

import Control.Applicative (liftA2, Alternative(..))
import Data.Function (on)
import Data.Functor.Classes
import Data.Semigroup
import GHC.Generics

import Generic.Data.Internal.Utils (from', to', liftG2)

-- * 'Eq'

-- | Generic @('==')@.
--
-- @
-- instance 'Eq' MyType where
--   ('==') = 'geq'
-- @
geq :: (Generic a, Eq (Rep a ())) => a -> a -> Bool
geq :: a -> a -> Bool
geq = Rep a () -> Rep a () -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Rep a () -> Rep a () -> Bool) -> (a -> Rep a ()) -> a -> a -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` a -> Rep a ()
forall a. Generic a => a -> Rep a ()
from'

-- * 'Ord'

-- | Generic 'compare'.
--
-- @
-- instance 'Ord' MyType where
--   'compare' = 'gcompare'
-- @
gcompare :: (Generic a, Ord (Rep a ())) => a -> a -> Ordering
gcompare :: a -> a -> Ordering
gcompare = Rep a () -> Rep a () -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Rep a () -> Rep a () -> Ordering)
-> (a -> Rep a ()) -> a -> a -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` a -> Rep a ()
forall a. Generic a => a -> Rep a ()
from'

-- * 'Semigroup'

-- | Generic @('<>')@ (or 'mappend').
--
-- @
-- instance 'Semigroup' MyType where
--   ('<>') = 'gmappend'
-- @
--
-- See also 'gmempty'.
gmappend :: (Generic a, Semigroup (Rep a ())) => a -> a -> a
gmappend :: a -> a -> a
gmappend = \a
a a
b -> Rep a () -> a
forall a x. Generic a => Rep a x -> a
to (a -> Rep a ()
forall a. Generic a => a -> Rep a ()
from' a
a Rep a () -> Rep a () -> Rep a ()
forall a. Semigroup a => a -> a -> a
<> a -> Rep a ()
forall a. Generic a => a -> Rep a ()
from' a
b)

-- * 'Monoid'

-- | Generic 'mempty'.
--
-- @
-- instance 'Monoid' MyType where
--   'mempty' = 'gmempty'
-- @
gmempty :: (Generic a, Monoid (Rep a ())) => a
gmempty :: a
gmempty = Rep a () -> a
forall a. Generic a => Rep a () -> a
to' Rep a ()
forall a. Monoid a => a
mempty

-- | Generic @('<>')@ (or @'mappend'@).
--
-- The difference from `gmappend' is the 'Monoid' constraint instead of
-- 'Semigroup', for older versions of base where 'Semigroup' is not a
-- superclass of 'Monoid'.
gmappend' :: (Generic a, Monoid (Rep a ())) => a -> a -> a
gmappend' :: a -> a -> a
gmappend' = \a
a a
b -> Rep a () -> a
forall a x. Generic a => Rep a x -> a
to (a -> Rep a ()
forall a. Generic a => a -> Rep a ()
from' a
a Rep a () -> Rep a () -> Rep a ()
forall a. Monoid a => a -> a -> a
`mappend` a -> Rep a ()
forall a. Generic a => a -> Rep a ()
from' a
b)

-- * 'Functor'

-- | Generic 'fmap'.
--
-- @
-- instance 'Functor' MyTypeF where
--   'fmap' = 'gfmap'
-- @
gfmap :: (Generic1 f, Functor (Rep1 f)) => (a -> b) -> f a -> f b
gfmap :: (a -> b) -> f a -> f b
gfmap = \a -> b
f -> Rep1 f b -> f b
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (Rep1 f b -> f b) -> (f a -> Rep1 f b) -> f a -> f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> Rep1 f a -> Rep1 f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (Rep1 f a -> Rep1 f b) -> (f a -> Rep1 f a) -> f a -> Rep1 f b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1

-- | Generic @('<$')@.
--
-- See also 'gfmap'.
gconstmap :: (Generic1 f, Functor (Rep1 f)) => a -> f b -> f a
gconstmap :: a -> f b -> f a
gconstmap = \a
a -> Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (Rep1 f a -> f a) -> (f b -> Rep1 f a) -> f b -> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a
a a -> Rep1 f b -> Rep1 f a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$) (Rep1 f b -> Rep1 f a) -> (f b -> Rep1 f b) -> f b -> Rep1 f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f b -> Rep1 f b
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1

-- * 'Applicative'

-- | Generic 'pure'.
--
-- @
-- instance 'Applicative' MyTypeF where
--   'pure' = 'gpure'
--   ('<*>') = 'gap'
-- @
gpure :: (Generic1 f, Applicative (Rep1 f)) => a -> f a
gpure :: a -> f a
gpure = Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (Rep1 f a -> f a) -> (a -> Rep1 f a) -> a -> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Rep1 f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

-- | Generic @('<*>')@ (or 'Control.Monad.ap').
--
-- See also 'gpure'.
gap :: (Generic1 f, Applicative (Rep1 f)) => f (a -> b) -> f a -> f b
gap :: f (a -> b) -> f a -> f b
gap = (Rep1 f (a -> b) -> Rep1 f a -> Rep1 f b)
-> f (a -> b) -> f a -> f b
forall k (f :: k -> *) (a :: k) (b :: k) (c :: k).
Generic1 f =>
(Rep1 f a -> Rep1 f b -> Rep1 f c) -> f a -> f b -> f c
liftG2 Rep1 f (a -> b) -> Rep1 f a -> Rep1 f b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
(<*>)

-- | Generic 'liftA2'.
--
-- See also 'gpure'.
gliftA2 :: (Generic1 f, Applicative (Rep1 f)) => (a -> b -> c) -> f a -> f b -> f c
gliftA2 :: (a -> b -> c) -> f a -> f b -> f c
gliftA2 = (Rep1 f a -> Rep1 f b -> Rep1 f c) -> f a -> f b -> f c
forall k (f :: k -> *) (a :: k) (b :: k) (c :: k).
Generic1 f =>
(Rep1 f a -> Rep1 f b -> Rep1 f c) -> f a -> f b -> f c
liftG2 ((Rep1 f a -> Rep1 f b -> Rep1 f c) -> f a -> f b -> f c)
-> ((a -> b -> c) -> Rep1 f a -> Rep1 f b -> Rep1 f c)
-> (a -> b -> c)
-> f a
-> f b
-> f c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b -> c) -> Rep1 f a -> Rep1 f b -> Rep1 f c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2

-- * 'Alternative'

-- | Generic 'empty'.
--
-- @
-- instance 'Alternative' MyTypeF where
--   'empty' = 'gempty'
--   ('<|>') = 'galt'
-- @
gempty :: (Generic1 f, Alternative (Rep1 f)) => f a
gempty :: f a
gempty = Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 Rep1 f a
forall (f :: * -> *) a. Alternative f => f a
empty

-- | Generic ('<|>').
--
-- See also 'gempty'.
galt :: (Generic1 f, Alternative (Rep1 f)) => f a -> f a -> f a
galt :: f a -> f a -> f a
galt = (Rep1 f a -> Rep1 f a -> Rep1 f a) -> f a -> f a -> f a
forall k (f :: k -> *) (a :: k) (b :: k) (c :: k).
Generic1 f =>
(Rep1 f a -> Rep1 f b -> Rep1 f c) -> f a -> f b -> f c
liftG2 Rep1 f a -> Rep1 f a -> Rep1 f a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>)

-- * 'Foldable'

-- | Generic 'foldMap'.
--
-- @
-- instance 'Foldable' MyTypeF where
--   'foldMap' = 'gfoldMap'
-- @
--
-- This is deprecated but kept around just for reference.
{-# DEPRECATED gfoldMap "This definition has been replaced with 'Generic.Data.Internal.gfoldMap'." #-}
gfoldMap :: (Generic1 f, Foldable (Rep1 f), Monoid m) => (a -> m) -> f a -> m
gfoldMap :: (a -> m) -> f a -> m
gfoldMap = \a -> m
f -> (a -> m) -> Rep1 f a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f (Rep1 f a -> m) -> (f a -> Rep1 f a) -> f a -> m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1

-- | Generic 'foldr'.
--
-- @
-- instance 'Foldable' MyTypeF where
--   'foldr' = 'gfoldr'
-- @
--
-- See also 'gfoldMap'.
gfoldr :: (Generic1 f, Foldable (Rep1 f)) => (a -> b -> b) -> b -> f a -> b
gfoldr :: (a -> b -> b) -> b -> f a -> b
gfoldr = \a -> b -> b
f b
b -> (a -> b -> b) -> b -> Rep1 f a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> b -> b
f b
b (Rep1 f a -> b) -> (f a -> Rep1 f a) -> f a -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1
-- Note: this one is not deprecated because inlining Just Works.

-- * 'Traversable'

-- | Generic 'traverse'.
--
-- @
-- instance 'Traversable' MyTypeF where
--   'traverse' = 'gtraverse'
-- @
--
-- This is deprecated but kept around just for reference.
{-# DEPRECATED gtraverse "This definition has been replaced with 'Generic.Data.Internal.gtraverse'." #-}
gtraverse
  :: (Generic1 f, Traversable (Rep1 f), Applicative m)
  => (a -> m b) -> f a -> m (f b)
gtraverse :: (a -> m b) -> f a -> m (f b)
gtraverse = \a -> m b
f -> (Rep1 f b -> f b) -> m (Rep1 f b) -> m (f b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Rep1 f b -> f b
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (m (Rep1 f b) -> m (f b))
-> (f a -> m (Rep1 f b)) -> f a -> m (f b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> m b) -> Rep1 f a -> m (Rep1 f b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> m b
f (Rep1 f a -> m (Rep1 f b))
-> (f a -> Rep1 f a) -> f a -> m (Rep1 f b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1

-- | Generic 'sequenceA'.
--
-- @
-- instance 'Traversable' MyTypeF where
--   'sequenceA' = 'gsequenceA'
-- @
--
-- See also 'gtraverse'.
--
-- This is deprecated but kept around just for reference.
{-# DEPRECATED gsequenceA "This definition has been replaced with 'Generic.Data.Internal.gsequenceA'." #-}
gsequenceA
  :: (Generic1 f, Traversable (Rep1 f), Applicative m)
  => f (m a) -> m (f a)
gsequenceA :: f (m a) -> m (f a)
gsequenceA = (Rep1 f a -> f a) -> m (Rep1 f a) -> m (f a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (m (Rep1 f a) -> m (f a))
-> (f (m a) -> m (Rep1 f a)) -> f (m a) -> m (f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep1 f (m a) -> m (Rep1 f a)
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA (Rep1 f (m a) -> m (Rep1 f a))
-> (f (m a) -> Rep1 f (m a)) -> f (m a) -> m (Rep1 f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f (m a) -> Rep1 f (m a)
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1

-- * 'Eq1'

-- | Generic 'liftEq'.
gliftEq :: (Generic1 f, Eq1 (Rep1 f)) => (a -> b -> Bool) -> f a -> f b -> Bool
gliftEq :: (a -> b -> Bool) -> f a -> f b -> Bool
gliftEq = \a -> b -> Bool
(==.) f a
a f b
b -> (a -> b -> Bool) -> Rep1 f a -> Rep1 f b -> Bool
forall (f :: * -> *) a b.
Eq1 f =>
(a -> b -> Bool) -> f a -> f b -> Bool
liftEq a -> b -> Bool
(==.) (f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a
a) (f b -> Rep1 f b
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f b
b)

-- * 'Ord1'

-- | Generic 'liftCompare'.
gliftCompare
  :: (Generic1 f, Ord1 (Rep1 f))
  => (a -> b -> Ordering) -> f a -> f b -> Ordering
gliftCompare :: (a -> b -> Ordering) -> f a -> f b -> Ordering
gliftCompare = \a -> b -> Ordering
compare' f a
a f b
b -> (a -> b -> Ordering) -> Rep1 f a -> Rep1 f b -> Ordering
forall (f :: * -> *) a b.
Ord1 f =>
(a -> b -> Ordering) -> f a -> f b -> Ordering
liftCompare a -> b -> Ordering
compare' (f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a
a) (f b -> Rep1 f b
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f b
b)