{-# LANGUAGE TypeApplications #-}

{-# OPTIONS_GHC -Wwarn #-}

module Data.Record.Generic.Eq (
    geq
  , gcompare
  ) where

import Data.Record.Generic
import qualified Data.Record.Generic.Rep as Rep

-- | Generic equality function
--
-- Typical usage:
--
-- > instance Eq T where
-- >   (==) = geq
--
-- TODO: Should we worry about short-circuiting here?
geq :: (Generic a, Constraints a Eq) => a -> a -> Bool
geq :: a -> a -> Bool
geq = \a
x a
y ->
      [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and
    ([Bool] -> Bool)
-> (Rep (K Bool) a -> [Bool]) -> Rep (K Bool) a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep (K Bool) a -> [Bool]
forall a b. Rep (K a) b -> [a]
Rep.collapse
    (Rep (K Bool) a -> Bool) -> Rep (K Bool) a -> Bool
forall a b. (a -> b) -> a -> b
$ Proxy Eq
-> (forall x. Eq x => I x -> I x -> K Bool x)
-> Rep I a
-> Rep I a
-> Rep (K Bool) a
forall a (c :: * -> Constraint) (f :: * -> *) (g :: * -> *)
       (h :: * -> *).
(Generic a, Constraints a c) =>
Proxy c
-> (forall x. c x => f x -> g x -> h x)
-> Rep f a
-> Rep g a
-> Rep h a
Rep.czipWith (Proxy Eq
forall k (t :: k). Proxy t
Proxy @Eq) forall x. Eq x => I x -> I x -> K Bool x
compareField (a -> Rep I a
forall a. Generic a => a -> Rep I a
from a
x) (a -> Rep I a
forall a. Generic a => a -> Rep I a
from a
y)
  where
    compareField :: Eq x => I x -> I x -> K Bool x
    compareField :: I x -> I x -> K Bool x
compareField (I x
x) (I x
y) = Bool -> K Bool x
forall k a (b :: k). a -> K a b
K (x
x x -> x -> Bool
forall a. Eq a => a -> a -> Bool
== x
y)

gcompare :: (Generic a, Constraints a Ord) => a -> a -> Ordering
gcompare :: a -> a -> Ordering
gcompare = \a
x a
y ->
      [Ordering] -> Ordering
forall a. Monoid a => [a] -> a
mconcat
    ([Ordering] -> Ordering)
-> (Rep (K Ordering) a -> [Ordering])
-> Rep (K Ordering) a
-> Ordering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep (K Ordering) a -> [Ordering]
forall a b. Rep (K a) b -> [a]
Rep.collapse
    (Rep (K Ordering) a -> Ordering) -> Rep (K Ordering) a -> Ordering
forall a b. (a -> b) -> a -> b
$ Proxy Ord
-> (forall x. Ord x => I x -> I x -> K Ordering x)
-> Rep I a
-> Rep I a
-> Rep (K Ordering) a
forall a (c :: * -> Constraint) (f :: * -> *) (g :: * -> *)
       (h :: * -> *).
(Generic a, Constraints a c) =>
Proxy c
-> (forall x. c x => f x -> g x -> h x)
-> Rep f a
-> Rep g a
-> Rep h a
Rep.czipWith (Proxy Ord
forall k (t :: k). Proxy t
Proxy @Ord) forall x. Ord x => I x -> I x -> K Ordering x
compareField (a -> Rep I a
forall a. Generic a => a -> Rep I a
from a
x) (a -> Rep I a
forall a. Generic a => a -> Rep I a
from a
y)
  where
    compareField :: Ord x => I x -> I x -> K Ordering x
    compareField :: I x -> I x -> K Ordering x
compareField (I x
x) (I x
y) = Ordering -> K Ordering x
forall k a (b :: k). a -> K a b
K (x -> x -> Ordering
forall a. Ord a => a -> a -> Ordering
compare x
x x
y)