Skip to content

Commit

Permalink
Merge pull request #5 from lemastero/wedge_can_instances_properties
Browse files Browse the repository at this point in the history
Wedge Can instances properties
  • Loading branch information
lemastero authored Jun 25, 2022
2 parents 08ccfa1 + de2513b commit 7fe338f
Show file tree
Hide file tree
Showing 6 changed files with 281 additions and 57 deletions.
124 changes: 76 additions & 48 deletions src/Data/Can.agda
Original file line number Diff line number Diff line change
Expand Up @@ -50,51 +50,69 @@ data Can (A : Set lA)(B : Set lB) : Set (lA ⊔ lB) where
eno : B -> Can A B
two : A -> B -> Can A B

{-
Can elimination rule
A : Type B Type C : Type
c: C abc : A->B->C
ab: A->B bc: B -> C
c: Can A B
-------------------
c : C
-}
fold : C -> (A -> C) -> (B -> C) -> (A -> B -> C) -> Can A B -> C
fold c _ _ _ non = c
fold c ac _ _ (one a) = ac a
fold c _ bc _ (eno b) = bc b
fold c _ _ _ non = c
fold c ac _ _ (one a) = ac a
fold c _ bc _ (eno b) = bc b
fold c _ _ abc (two a b) = abc a b

foldWithMerge : C -> (A -> C) -> (B -> C) -> (C -> C -> C) -> Can A B -> C
foldWithMerge c _ _ _ non = c
foldWithMerge c ac _ _ (one a) = ac a
foldWithMerge c _ bc _ (eno b) = bc b
foldWithMerge c _ _ _ non = c
foldWithMerge c ac _ _ (one a) = ac a
foldWithMerge c _ bc _ (eno b) = bc b
foldWithMerge _ ac bc m (two a b) = m (ac a) (bc b)

-- associativity

reassocLR : Can (Can A B) C -> Can A (Can B C)
reassocLR = {! !}
reassocLR non = non
reassocLR (one non) = non
reassocLR (one (one a)) = one a
reassocLR (one (eno b)) = eno (one b)
reassocLR (one (two a b)) = two a (one b)
reassocLR (eno c) = eno (eno c)
reassocLR (two non c) = eno (eno c)
reassocLR (two (one a) c) = two a (eno c)
reassocLR (two (eno b) c) = eno (two b c)
reassocLR (two (two a b) c) = two a (two b c)

reassocRL : Can A (Can B C) -> Can (Can A B) C
reassocRL = {! !}
reassocRL non = non
reassocRL (one a) = one (one a)
reassocRL (eno non) = non
reassocRL (eno (one b)) = one (eno b)
reassocRL (eno (eno c)) = eno c
reassocRL (eno (two b c)) = two (eno b) c
reassocRL (two a non) = one (one a)
reassocRL (two a (one b)) = one (two a b)
reassocRL (two a (eno c)) = two (one a) c
reassocRL (two a (two b c)) = two (two a b) c

-- commutativity / symmetry

swap : Can A B -> Can B A
swap non = non
swap (one a) = eno a
swap (eno b) = one b
swap non = non
swap (one a) = eno a
swap (eno b) = one b
swap (two a b) = two b a

-- distributivity

distributeCan : Can (A * B) C -> ((Can A C) * (Can B C))
distributeCan = {! !}
distributeCan non = (non , non)
distributeCan (one (a , b)) = (one a) , (one b)
distributeCan (eno c) = (eno c) , (eno c)
distributeCan (two (a , b) c) = (two a c) , (eno c)

codistributeCan : (Can A C) + (Can B C) -> Can (A + B) C
codistributeCan = {! !}
codistributeCan (left non) = non
codistributeCan (left (one a)) = one (left a)
codistributeCan (left (eno c)) = eno c
codistributeCan (left (two a c)) = two (left a) c
codistributeCan (right non) = non
codistributeCan (right (one b)) = one (right b)
codistributeCan (right (eno c)) = eno c
codistributeCan (right (two b c)) = two (right b) c

bimap : (A -> A') -> (B -> B') -> Can A B -> Can A' B'
bimap f g non = non
Expand All @@ -106,46 +124,50 @@ bipure : A -> B -> Can A B
bipure = two

biap : Can (A -> A') (B -> B') -> Can A B -> Can A' B'
biap (one fa) (one a) = one (fa a)
biap (one fa) (two a b) = one (fa a)
biap (eno fb) (eno b) = eno (fb b)
biap (eno fb) (two a b) = eno (fb b)
biap (one fa) (one a) = one (fa a)
biap (one fa) (two a b) = one (fa a)
biap (eno fb) (eno b) = eno (fb b)
biap (eno fb) (two a b) = eno (fb b)
biap (two fa fb) (two a b) = two (fa a) (fb b)
biap (two fa fb) (one a) = one (fa a)
biap (two fa fb) (eno b) = eno (fb b)
biap _ _ = non
biap (two fa fb) (one a) = one (fa a)
biap (two fa fb) (eno b) = eno (fb b)
biap _ _ = non

-- TODO add to Haskell
canProduct : Maybe A -> Maybe B -> Can A B
canProduct (just a) (just b) = two a b
canProduct (just a) nothing = one a
canProduct nothing (just b) = eno b
canProduct nothing nothing = non
canProduct (just a) nothing = one a
canProduct nothing (just b) = eno b
canProduct nothing nothing = non

-- TODO add to Haskell
canSum : Maybe A + Maybe B -> Can A B
canSum (left (just a)) = one a
canSum (left nothing) = non
canSum (left (just a)) = one a
canSum (left nothing) = non
canSum (right (just b)) = eno b
canSum (right nothing) = non
canSum (right nothing) = non

-- TODO add to Haskell
canSum2 : Maybe (A + B) -> Can A B
canSum2 (just (left a)) = one a
canSum2 (just (right b)) = eno b
canSum2 nothing = non

-- TODO canFst (canProduct ma mb) = ma
canFst : Can A B -> Maybe A
canFst (one a) = just a
canFst (one a) = just a
canFst (two a b) = just a
canFst _ = nothing
canFst _ = nothing

-- TODO canSnd (canProduct ma mb) = mb
canSnd : Can A B -> Maybe B
canSnd (eno b) = just b
canSnd (eno b) = just b
canSnd (two a b) = just b
canSnd _ = nothing
canSnd _ = nothing

fromProduct : A * B -> Can A B
fromProduct (a , b) = two a b

fromSum : A + B -> Can A B
fromSum (left a) = one a
fromSum (left a) = one a
fromSum (right b) = eno b

Can-Induction : {A : Set lA} {B : Set lB} (P : Can A B -> Set lP)
Expand All @@ -154,13 +176,19 @@ Can-Induction : {A : Set lA} {B : Set lB} (P : Can A B -> Set lP)
-> ((b : B) -> P (eno b))
-> ((a : A) -> (b : B) -> P (two a b))
-> (s : Can A B) -> P s
Can-Induction P pn po pe pt non = pn
Can-Induction P pn po pe pt (one a) = po a
Can-Induction P pn po pe pt (eno b) = pe b
Can-Induction P pn po pe pt non = pn
Can-Induction P pn po pe pt (one a) = po a
Can-Induction P pn po pe pt (eno b) = pe b
Can-Induction P pn po pe pt (two a b) = pt a b

canCurry : (Can A B -> Maybe C) -> Maybe A -> Maybe B -> Maybe C
canCurry = {! !}
canCurry f (just a) (just b) = f (two a b)
canCurry f (just a) nothing = f (one a)
canCurry f nothing (just b) = f (eno b)
canCurry f nothing nothing = f non

canUncurry : (Maybe A -> Maybe B -> Maybe C) -> Can A B -> Maybe C
canUncurry = {! !}
canUncurry f non = f nothing nothing
canUncurry f (one a) = f (just a) nothing
canUncurry f (eno b) = f nothing (just b)
canUncurry f (two a b) = f (just a) (just b)
21 changes: 21 additions & 0 deletions src/Data/Can/Instances.agda
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{-# OPTIONS --without-K --safe #-}

module Data.Can.Instances where

open import Data.Can using (Can)
open import Data.Can.Properties using (≡-dec)
open import Level using (Level)
open import Relation.Binary.PropositionalEquality using (_≡_; isDecEquivalence)
open import Relation.Binary.TypeClasses using (IsDecEquivalence) renaming (_≟_ to _=?_)

private
variable
lA lB : Level
A : Set lA
B : Set lB

instance
Can-≡-isDecEquivalence : {{IsDecEquivalence {A = A} _≡_}}
-> {{IsDecEquivalence {A = B} _≡_}}
-> IsDecEquivalence {A = Can A B} _≡_
Can-≡-isDecEquivalence = isDecEquivalence (≡-dec _=?_ _=?_)
93 changes: 93 additions & 0 deletions src/Data/Can/Properties.agda
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{-# OPTIONS --without-K --safe #-}

module Data.Can.Properties where

open import Data.Can
open import Data.Product using (_×_; _,_; <_,_>; uncurry)
open import Function.Base using (id) renaming (_∘_ to _compose_)
open import Level using (Level)
open import Relation.Binary.PropositionalEquality
using (_≡_; refl)
renaming (cong₂ to cong2)
open import Relation.Binary using (Decidable)
open import Relation.Binary.PropositionalEquality renaming (_≗_ to _==_)
open import Relation.Nullary using (yes; no)
open import Relation.Nullary.Decidable renaming (map′ to dec-map)
open import Relation.Nullary.Product renaming (_×-dec_ to _*-dec_)

private
variable
lA lB lP lA' lB' : Level
A : Set lA
B : Set lB
A' : Set lA'
B' : Set lB'

-- if f1 = f2 and g1 = g2 then bimap f1 g1 = bimap f2 g2
bimap-cong : forall {f1 f2 : A -> A'} {g1 g2 : B -> B'}
-> f1 == f2
-> g1 == g2
-> (bimap f1 g1) == (bimap f2 g2)
bimap-cong f1=f2 g1=g2 non = refl
bimap-cong f1=f2 g1=g2 (one a) = cong one (f1=f2 a)
bimap-cong f1=f2 g1=g2 (eno b) = cong eno (g1=g2 b)
bimap-cong f1=f2 g1=g2 (two a b) = cong₂ two (f1=f2 a) (g1=g2 b)

-- swap . swap == id
swap-involutive : (swap {A = A} {B = B} compose swap) == id
swap-involutive non = refl
swap-involutive (one a) = refl
swap-involutive (eno b) = refl
swap-involutive (two a b) = refl

-- Equality

module _ {la lb} {A : Set la} {B : Set lb} where

one-injective : forall {a a' : A}
-> one {B = B} a ≡ one a'
-> a ≡ a'
one-injective refl = refl

eno-injective : forall {b b' : B}
-> eno {A = A} b ≡ eno b'
-> b ≡ b'
eno-injective refl = refl

two-injective-left : forall {a a' : A} {b b' : B}
-> two a b ≡ two a' b'
-> a ≡ a'
two-injective-left refl = refl

two-injective-right : forall {a a' : A} {b b' : B}
-> two a b ≡ two a' b'
-> b ≡ b'
two-injective-right refl = refl

two-injective : forall {a a' : A} {b b' : B}
-> two a b ≡ two a' b'
-> (a ≡ a') × (b ≡ b')
two-injective = < two-injective-left , two-injective-right >

≡-dec : Decidable _≡_ -> Decidable _≡_ -> Decidable {A = Can A B} _≡_
≡-dec deca decb non non = yes refl
≡-dec deca decb (one a1) (one a2) =
dec-map (cong one) one-injective (deca a1 a2)
≡-dec deca decb (eno b1) (eno b2) =
dec-map (cong eno) eno-injective (decb b1 b2)
≡-dec deca decb (two a1 b1) (two a2 b2) =
dec-map ((uncurry (cong2 two)))
two-injective
(deca a1 a2 *-dec decb b1 b2)
≡-dec deca decb non (one a) = no \ ()
≡-dec deca decb non (eno b) = no \ ()
≡-dec deca decb non (two a b) = no \ ()
≡-dec deca decb (one a) non = no \ ()
≡-dec deca decb (one a) (eno b) = no \ ()
≡-dec deca decb (one a1) (two a2 b2) = no \ ()
≡-dec deca decb (eno b) non = no \ ()
≡-dec deca decb (eno b) (one a) = no \ ()
≡-dec deca decb (eno b1) (two a b2) = no \ ()
≡-dec deca decb (two a b) non = no \ ()
≡-dec deca decb (two a1 b) (one a2) = no \ ()
≡-dec deca decb (two a b1) (eno b2) = no \ ()
13 changes: 4 additions & 9 deletions src/Data/Wedge.agda
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,11 @@ swap (there b) = here b
-- Wedge associativity

reassocLR : Wedge (Wedge A B) C -> Wedge A (Wedge B C)
reassocLR (here (here a)) = here a
reassocLR (here (there b)) = there (here b)
reassocLR (there c) = there (there c)
reassocLR _ = nowhere
reassocLR (here (there b)) = there (here b)
reassocLR (here (here a)) = here a
reassocLR (here nowhere) = nowhere
reassocLR nowhere = nowhere

reassocRL : Wedge A (Wedge B C) -> Wedge (Wedge A B) C
reassocRL nowhere = nowhere
Expand All @@ -112,8 +113,6 @@ reassocRL (there nowhere) = nowhere
reassocRL (there (here b)) = here (there b)
reassocRL (there (there c)) = there c

--

-- conversions

fromSum : A + B -> Wedge A B
Expand All @@ -126,8 +125,6 @@ quotWedge (left nothing) = nowhere
quotWedge (right (just b)) = there b
quotWedge (right nothing) = nowhere

-- 1 + (A + B) <=> Wedge A B

-- collapses both nothing into single nowhere
toWedge : Maybe (A + B) -> Wedge A B
toWedge (just (left a)) = here a
Expand All @@ -141,12 +138,10 @@ fromWedge (there b) = just (right b)

-- projections

-- TODO fromHere (quotWedge Nothing mb) = mb
fromHere : Wedge A B -> Maybe A
fromHere (here a) = just a
fromHere _ = nothing

-- TODO fromThere (quotWedge ma Nothing) = ma
fromThere : Wedge A B -> Maybe B
fromThere (there b) = just b
fromThere _ = nothing
Expand Down
21 changes: 21 additions & 0 deletions src/Data/Wedge/Instances.agda
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{-# OPTIONS --without-K --safe #-}

module Data.Wedge.Instances where

open import Data.Wedge using (Wedge)
open import Data.Wedge.Properties using (≡-dec)
open import Level using (Level)
open import Relation.Binary.PropositionalEquality using (_≡_; isDecEquivalence)
open import Relation.Binary.TypeClasses using (IsDecEquivalence) renaming (_≟_ to _=?_)

private
variable
lA lB : Level
A : Set lA
B : Set lB

instance
Wedge-≡-isDecEquivalence : {{IsDecEquivalence {A = A} _≡_}}
-> {{IsDecEquivalence {A = B} _≡_}}
-> IsDecEquivalence {A = Wedge A B} _≡_
Wedge-≡-isDecEquivalence = isDecEquivalence (≡-dec _=?_ _=?_)
Loading

0 comments on commit 7fe338f

Please sign in to comment.