module Haskell.Law.Eq.Instances where
open import Agda.Builtin.Char.Properties renaming (primCharToNatInjective to c2n-injective)
open import Agda.Builtin.Word.Properties renaming (primWord64ToNatInjective to w2n-injective)
open import Haskell.Prim
open import Haskell.Prim.Eq
open import Haskell.Prim.Either using ( Either; Left; Right )
open import Haskell.Prim.Int using ( Int; int64 )
open import Haskell.Prim.Maybe
open import Haskell.Prim.Ord using ( Ordering; LT; GT; EQ )
open import Haskell.Prim.Tuple
open import Haskell.Prim.Word using ( Word )
open import Haskell.Extra.Dec using ( mapReflects )
open import Haskell.Law.Eq.Def
open import Haskell.Law.Equality
open import Haskell.Law.Either
open import Haskell.Law.Int
open import Haskell.Law.Integer
open import Haskell.Law.List using ( ∷-injective-left; ∷-injective-right )
open import Haskell.Law.Maybe
open import Haskell.Law.Nat
instance
iLawfulEqNat : IsLawfulEq Nat
iLawfulEqNat .isEquality zero zero = refl
iLawfulEqNat .isEquality zero (suc _) = λ ()
iLawfulEqNat .isEquality (suc _) zero = λ ()
iLawfulEqNat .isEquality (suc x) (suc y) = mapReflects
(cong suc)
suc-injective
(isEquality x y)
iLawfulEqWord : IsLawfulEq Word
iLawfulEqWord .isEquality x y
with (w2n x) in h₁ | (w2n y) in h₂
... | a | b = mapReflects
(λ h → w2n-injective x y $ sym $ trans (trans h₂ $ sym h) (sym h₁))
(λ h → trans (sym $ trans (cong w2n (sym h)) h₁) h₂)
(isEquality a b)
iLawfulEqBool : IsLawfulEq Bool
iLawfulEqBool .isEquality False False = refl
iLawfulEqBool .isEquality False True = λ()
iLawfulEqBool .isEquality True False = λ()
iLawfulEqBool .isEquality True True = refl
iLawfulEqChar : IsLawfulEq Char
iLawfulEqChar .isEquality x y
with (c2n x) in h₁ | (c2n y) in h₂
... | a | b = mapReflects { a ≡ b } { x ≡ y } { eqNat a b }
(λ h → c2n-injective x y $ sym $ trans (trans h₂ $ sym h) (sym h₁))
(λ h → trans (sym $ trans (cong c2n (sym h)) h₁) h₂)
(isEquality a b)
iLawfulEqEither : ⦃ iEqA : Eq a ⦄ → ⦃ iEqB : Eq b ⦄
→ ⦃ IsLawfulEq a ⦄ → ⦃ IsLawfulEq b ⦄
→ IsLawfulEq (Either a b)
iLawfulEqEither .isEquality (Left _) (Right _) = λ ()
iLawfulEqEither .isEquality (Right _) (Left _) = λ ()
iLawfulEqEither .isEquality (Left x) (Left y) = mapReflects
(cong Left) (Left-injective) (isEquality x y)
iLawfulEqEither .isEquality (Right x) (Right y) = mapReflects
(cong Right) (Right-injective) (isEquality x y)
iLawfulEqInt : IsLawfulEq Int
iLawfulEqInt .isEquality (int64 x) (int64 y) = mapReflects
(cong int64) int64-injective (isEquality x y)
iLawfulEqInteger : IsLawfulEq Integer
iLawfulEqInteger .isEquality (pos n) (pos m) = mapReflects
(cong pos) pos-injective (isEquality n m)
iLawfulEqInteger .isEquality (pos _) (negsuc _) = λ ()
iLawfulEqInteger .isEquality (negsuc _) (pos _) = λ ()
iLawfulEqInteger .isEquality (negsuc n) (negsuc m) = mapReflects
(cong negsuc) neg-injective (isEquality n m)
iLawfulEqList : ⦃ iEqA : Eq a ⦄ → ⦃ IsLawfulEq a ⦄ → IsLawfulEq (List a)
iLawfulEqList .isEquality [] [] = refl
iLawfulEqList .isEquality [] (_ ∷ _) = λ ()
iLawfulEqList .isEquality (_ ∷ _) [] = λ ()
iLawfulEqList .isEquality (x ∷ xs) (y ∷ ys)
with (x == y) in h₁
... | True = mapReflects
(λ h → cong₂ (_∷_) (equality x y h₁) h)
∷-injective-right
(isEquality xs ys)
... | False = λ h → (nequality x y h₁) (∷-injective-left h)
iLawfulEqMaybe : ⦃ iEqA : Eq a ⦄ → ⦃ IsLawfulEq a ⦄ → IsLawfulEq (Maybe a)
iLawfulEqMaybe .isEquality Nothing Nothing = refl
iLawfulEqMaybe .isEquality Nothing (Just _) = λ()
iLawfulEqMaybe .isEquality (Just _) Nothing = λ()
iLawfulEqMaybe .isEquality (Just x) (Just y) = mapReflects
(cong Just) Just-injective (isEquality x y)
iLawfulEqOrdering : IsLawfulEq Ordering
iLawfulEqOrdering .isEquality LT LT = refl
iLawfulEqOrdering .isEquality LT EQ = λ()
iLawfulEqOrdering .isEquality LT GT = λ()
iLawfulEqOrdering .isEquality EQ LT = λ()
iLawfulEqOrdering .isEquality EQ EQ = refl
iLawfulEqOrdering .isEquality EQ GT = λ()
iLawfulEqOrdering .isEquality GT LT = λ()
iLawfulEqOrdering .isEquality GT EQ = λ()
iLawfulEqOrdering .isEquality GT GT = refl
iLawfulEqTuple₂ : ⦃ iEqA : Eq a ⦄ ⦃ iEqB : Eq b ⦄
→ ⦃ IsLawfulEq a ⦄ → ⦃ IsLawfulEq b ⦄
→ IsLawfulEq (a × b)
iLawfulEqTuple₂ .isEquality (x₁ , x₂) (y₁ , y₂)
with (x₁ == y₁) in h₁
... | True = mapReflects
(λ h → cong₂ _,_ (equality x₁ y₁ h₁) h)
(cong snd)
(isEquality x₂ y₂)
... | False = λ h → exFalso (equality' x₁ y₁ (cong fst h)) h₁
iLawfulEqTuple₃ : ⦃ iEqA : Eq a ⦄ ⦃ iEqB : Eq b ⦄ ⦃ iEqC : Eq c ⦄
→ ⦃ IsLawfulEq a ⦄ → ⦃ IsLawfulEq b ⦄ → ⦃ IsLawfulEq c ⦄
→ IsLawfulEq (a × b × c)
iLawfulEqTuple₃ .isEquality (x₁ , x₂ , x₃) (y₁ , y₂ , y₃)
with (x₁ == y₁) in h₁
... | True = mapReflects
(λ h → cong₂ (λ a (b , c) → a , b , c) (equality x₁ y₁ h₁) h)
(cong λ h → snd₃ h , thd₃ h)
(isEquality (x₂ , x₃) (y₂ , y₃))
... | False = λ h → exFalso (equality' x₁ y₁ (cong fst₃ h)) h₁
iLawfulEqUnit : IsLawfulEq ⊤
iLawfulEqUnit .isEquality tt tt = refl