{-# language AllowAmbiguousTypes #-}
{-# language ConstraintKinds #-}
{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language FlexibleInstances #-}
{-# language MultiParamTypeClasses #-}
{-# language PolyKinds #-}
{-# language QuantifiedConstraints #-}
{-# language ScopedTypeVariables #-}
{-# language TypeApplications #-}
{-# language TypeFamilies #-}
{-# language TypeOperators #-}
{-# language UndecidableInstances #-}
module Generics.Kind.Derive.Eq where
import Data.Kind
import GHC.TypeLits
import Generics.Kind
geq' :: forall t. (GenericK t, GEq (RepK t), ReqsEq (RepK t) 'LoT0)
=> t -> t -> Bool
geq' x y = geq (fromK @_ @t @'LoT0 x) (fromK @_ @t @'LoT0 y)
class GEq (f :: LoT k -> Type) where
type family ReqsEq f (tys :: LoT k) :: Constraint
geq :: ReqsEq f tys => f tys -> f tys -> Bool
instance GEq U1 where
type ReqsEq U1 tys = ()
geq U1 U1 = True
instance GEq f => GEq (M1 i c f) where
type ReqsEq (M1 i c f) tys = ReqsEq f tys
geq (M1 x) (M1 y) = geq x y
instance (GEq f, GEq g) => GEq (f :+: g) where
type ReqsEq (f :+: g) tys = (ReqsEq f tys, ReqsEq g tys)
geq (L1 x) (L1 y) = geq x y
geq (R1 x) (R1 y) = geq x y
geq _ _ = False
instance (GEq f, GEq g) => GEq (f :*: g) where
type ReqsEq (f :*: g) tys = (ReqsEq f tys, ReqsEq g tys)
geq (x1 :*: x2) (y1 :*: y2) = geq x1 y1 && geq x2 y2
instance GEq (Field t) where
type ReqsEq (Field t) tys = Eq (Interpret t tys)
geq (Field x) (Field y) = x == y
instance GEq f => GEq (c :=>: f) where
type ReqsEq (c :=>: f) tys = ReqsEq f tys
-- really we want = Interpret c tys => GEq f tys
geq (SuchThat x) (SuchThat y) = geq x y
instance TypeError ('Text "Existentials are not supported")
=> GEq (Exists k f) where
type ReqsEq (Exists k f) tys = TypeError ('Text "Existentials are not supported")
geq = undefined