-- |
-- This package provides functionality for equality by only Constructors.
-- That means ConstrEq is ignore all parameters of a constructor and only makes a difference based on the constructor.
--
-- Let us look at an example:
--
-- @
-- data T = T1 | T2 Int | T3 Int
--   deriving 'Generic'
-- 
-- instance ConstrEq T
--
-- constrEq T1 (T2 0)     == False
-- constrEq T1 T1         == True
-- constrEq (T2 1) (T2 2) == True
-- constrEq (T2 3) (T3 3) == False
-- @
-- 


module Generics.Deriving.ConstrEq where

import GHC.Generics

import Data.Int
import System.IO (BufferMode, Handle, HandlePosn, IOMode, SeekMode)
import System.IO.Error (IOErrorType)
import Foreign.ForeignPtr (ForeignPtr)
import Foreign.Ptr
import Foreign.StablePtr (StablePtr)




class ConstrEq' f where
    constrEq' :: f p -> f p -> Bool


instance (ConstrEq' f) => ConstrEq' (M1 i t f) where
    constrEq' (M1 a) (M1 b) = constrEq' a b

instance (ConstrEq f) => ConstrEq' (K1 i f) where
    constrEq' (K1 a) (K1 b) = constrEq a b

instance ConstrEq' V1 where
    constrEq' _ _ = False

instance ConstrEq' U1 where
    constrEq' _ _ = True
    
instance (ConstrEq' f, ConstrEq' g) => ConstrEq' (f :+: g) where
    constrEq' (L1 _) (L1 _) = True
    constrEq' (R1 a) (R1 b) = constrEq' a b
    constrEq' _ _ = False

instance ConstrEq' (f :*: g) where
    constrEq' _ _ = True
    

class ConstrEq a where
    constrEq :: a -> a -> Bool
    default constrEq :: (Generic a, ConstrEq' (Rep a)) => a -> a -> Bool
    constrEq a b = constrEq' (from a) (from b)




    

instance ConstrEq Int where
  constrEq = (==)

instance ConstrEq Int8 where
  constrEq = (==)

instance ConstrEq Int16 where
  constrEq = (==)

instance ConstrEq Int32 where
  constrEq = (==)

instance ConstrEq Int64 where
  constrEq = (==)

instance ConstrEq Integer where
  constrEq = (==)

instance ConstrEq IntPtr where
  constrEq = (==)

instance ConstrEq IOError where
  constrEq = (==)

instance ConstrEq IOErrorType where
  constrEq = (==)

instance ConstrEq IOMode where
  constrEq = (==)

instance ConstrEq BufferMode where
  constrEq = (==)

instance ConstrEq Handle where
  constrEq = (==)

instance ConstrEq HandlePosn where
  constrEq = (==)

instance ConstrEq SeekMode where
  constrEq = (==)

instance ConstrEq (ForeignPtr a) where
  constrEq = (==)

instance ConstrEq (StablePtr a) where
  constrEq = (==)

instance ConstrEq Char where
  constrEq = (==)


ceqdefault :: (Generic a, ConstrEq' (Rep a)) => a -> a -> Bool
ceqdefault x y = constrEq' (from x) (from y)

instance ConstrEq a => ConstrEq [a] where
  constrEq = ceqdefault