{-# LANGUAGE GADTs #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UnicodeSyntax #-} module Abt.Class.HEq1 where import Control.Applicative import Data.Vinyl -- | Essentially, Martin-Löf's identity type. -- data a :=: b where Refl ∷ a :=: a -- | Type constructors are extensional. -- cong ∷ a :=: b → f a :=: f b cong Refl = Refl -- | Uniform variant of 'Eq' for indexed types. This is different from -- 'Data.Functor.Eq1' in that it is properly kind polymorphic and crucially -- heterogeneous, and it places no constraint on the index. Because it is -- heterogeneous, it is useful to project equality in the base space from -- equality in the total space. -- class HEq1 f where -- | When both sides are equal, give in addition a proof that their indices -- are equal; otherwise return 'Nothing'. -- heq1 ∷ f i → f j → Maybe (i :=: j) -- | A boolean version of 'heq1', which must agree with it. -- (===) ∷ f i → f j → Bool x === y = maybe False (const True) $ heq1 x y instance HEq1 el ⇒ HEq1 (Rec el) where heq1 RNil RNil = Just Refl heq1 (x :& xs) (y :& ys) | Just Refl ← heq1 x y = cong <$> heq1 xs ys heq1 _ _ = Nothing