------------------------------------------------------------------------------
-- Dependently typed functional languages - 2011-01

-- Leibniz's equality
------------------------------------------------------------------------------

-- Common options
{-# OPTIONS --double-check   #-}
{-# OPTIONS --exact-split    #-}
{-# OPTIONS --guardedness    #-}
{-# OPTIONS --no-sized-types #-}
{-# OPTIONS --warning=all    #-}
{-# OPTIONS --warning=error  #-}

-- Other options
{-# OPTIONS --no-universe-polymorphism #-}
{-# OPTIONS --safe                     #-}
{-# OPTIONS --without-K                #-}

module Lecture.LeibnizEquality where

open import Extra.Relation.Binary.PropositionalEquality

------------------------------------------------------------------------------
-- Introduction

-- Leibniz's law:
-- 'Two objects of the same type are equal if and only if they cannot
-- be distinguished by any property.' [Zhaohui 1994, §5.1.3]

-- Indiscernible: Incapable of being discerned. Not recognizable as distinct
-- (Merrian Webster).

-- Two parts of Leibniz's law: [Forrest 2010]
-- A. The identity of indiscernibles: ∀P(P x ↔ P y) → x ≐ y.

-- B. The indiscernibility of identicals: x ≐ y → ∀P(P x ↔ P y)

-- Luo, Zhaohui (1994). Computation and Reasoning. A Type Theory for
-- Computer Science. Oxford University Press.

-- Forrest, Peter (2010). The Identity of Indiscernibles.
-- http://plato.stanford.edu/entries/identity-indiscernible/.

------------------------------------------------------------------------------
-- Leibniz's equality [Zhaohui 1994]

-- (From Agda/examples/lib/Logic/Leibniz.agda)

infix 4 _≐_

_≐_  : {A : Set} → A → A → Set1
x ≐ y = (P : _ → Set) → P x → P y

-- Properties
≐-refl : {A : Set}{x : A} → x ≐ x
≐-refl P Px = Px

≐-sym : {A : Set}(x y : A) → x ≐ y → y ≐ x
≐-sym x y x≐y P Py = x≐y (λ z → P z → P x) (λ Px → Px) Py

≐-trans : {A : Set}{x y z : A} → x ≐ y → y ≐ z → x ≐ z
≐-trans x≐y y≐z P Px = y≐z P (x≐y P Px)

≐-subst : {A : Set}(P : A → Set){x y : A} → x ≐ y → P x → P y
≐-subst P x≐y = x≐y P

------------------------------------------------------------------------------
-- Leibniz's equality and the identity type

≐→≡ : {A : Set}{x y : A} → x ≐ y → x ≡ y
≐→≡ {x = x} x≐y = x≐y (λ z → x ≡ z) refl

≡→≐ : {A : Set}{x y : A} → x ≡ y → x ≐ y
≡→≐ refl P Px = Px