{-# OPTIONS --safe #-} module Choose where open import Prelude hiding (_⟨_⟩_) open import Data.Vec open import Path.Reasoning private variable n m k : ℕ data Choose (A : Type) : ℕ → ℕ → Type where ⟨_⟩ : A → Choose A zero m ⟨⟩ : Choose A (suc n) zero _**_ : Choose A (suc n) m → Choose A n m → Choose A (suc n) (suc m) cmap : (A → B) → Choose A n m → Choose B n m cmap f ⟨ x ⟩ = ⟨ f x ⟩ cmap f ⟨⟩ = ⟨⟩ cmap f (xs ** ys) = cmap f xs ** cmap f ys choose : ∀ n → Vec A m → Choose (Vec A n) n m choose zero _ = ⟨ [] ⟩ choose (suc n) [] = ⟨⟩ choose (suc n) (x ∷ xs) = choose (suc n) xs ** cmap (x ∷_) (choose n xs) sub : Vec A (suc n) → Vec (Vec A n) n sub (x ∷ []) = [] sub (x ∷ xs@(_ ∷ _)) = xs ∷ vmap (x ∷_) (sub xs) zw : (A → B → C) → Choose A n m → Choose B n m → Choose C n m zw f ⟨ x ⟩ ⟨ y ⟩ = ⟨ f x y ⟩ zw f ⟨⟩ ⟨⟩ = ⟨⟩ zw f (xsₗ ** xsᵣ) (ysₗ ** ysᵣ) = zw f xsₗ ysₗ ** zw f xsᵣ ysᵣ fill : ∀ n m → A → Choose A n m fill zero m x = ⟨ x ⟩ fill (suc n) zero x = ⟨⟩ fill (suc n) (suc m) x = fill (suc n) m x ** fill n m x up : Choose A k m → Choose (Vec A k) (suc k) m up ⟨ _ ⟩ = fill _ _ [] up ⟨⟩ = ⟨⟩ up (xs ** ys) = up xs ** zw _∷_ xs (up ys) private variable D E : Type zw-cmap-cmap : (f : B → D → E) (g : A → B) (h : C → D) (xs : Choose A n m) (ys : Choose C n m) → zw f (cmap g xs) (cmap h ys) ≡ zw (λ x y → f (g x) (h y)) xs ys zw-cmap-cmap f g h ⟨ x ⟩ ⟨ y ⟩ = refl zw-cmap-cmap f g h ⟨⟩ ⟨⟩ = refl zw-cmap-cmap f g h (xl ** xr) (yl ** yr) = cong₂ _**_ (zw-cmap-cmap f g h xl yl) (zw-cmap-cmap f g h xr yr) cmap-zw : (f : C → D) (g : A → B → C) (xs : Choose A n m) (ys : Choose B n m) → cmap f (zw g xs ys) ≡ zw (λ x y → f (g x y)) xs ys cmap-zw f g ⟨ x ⟩ ⟨ y ⟩ = refl cmap-zw f g ⟨⟩ ⟨⟩ = refl cmap-zw f g (xsₗ ** xsᵣ) (ysₗ ** ysᵣ) = cong₂ _**_ (cmap-zw f g xsₗ ysₗ) (cmap-zw f g xsᵣ ysᵣ) choose-prop : isProp A → isProp (Choose A n m) choose-prop prop ⟨ x ⟩ ⟨ y ⟩ = cong ⟨_⟩ (prop x y) choose-prop prop ⟨⟩ ⟨⟩ = refl choose-prop prop (xsₗ ** xsᵣ) (ysₗ ** ysᵣ) = cong₂ _**_ (choose-prop prop xsₗ ysₗ) (choose-prop prop xsᵣ ysᵣ) up-nat : (f : A → B) (xs : Choose A n m) → up (cmap f xs) ≡ cmap (vmap f) (up xs) up-nat f ⟨ x ⟩ = choose-prop isProp-[] _ _ up-nat f ⟨⟩ = refl up-nat f (xs ** ys) = cong₂ _**_ (up-nat f xs) $ zw _∷_ (cmap f xs) (up (cmap f ys)) ≡⟨ cong (zw _∷_ _) (up-nat f ys) ⟩ zw _∷_ (cmap f xs) (cmap (vmap f) (up ys)) ≡⟨ zw-cmap-cmap _∷_ f (vmap f) xs (up ys) ⟩ zw (λ z zs → vmap f (z ∷ zs)) xs (up ys) ≡˘⟨ cmap-zw (vmap f) _∷_ xs (up ys) ⟩ cmap (vmap f) (zw _∷_ xs (up ys)) ∎ cmap-comp : (g : B → C) (f : A → B) (xs : Choose A n m) → cmap g (cmap f xs) ≡ cmap (g ∘ f) xs cmap-comp g f ⟨ x ⟩ = refl cmap-comp g f ⟨⟩ = refl cmap-comp g f (xsₗ ** xsᵣ) = cong₂ _**_ (cmap-comp g f xsₗ) (cmap-comp g f xsᵣ) zw-sub : ∀ x (xs : Choose (Vec A (suc k)) n m) → cmap sub (cmap (x ∷_) xs) ≡ zw _∷_ xs (cmap (vmap (x ∷_) ∘ sub) xs) zw-sub x ⟨ _ ∷ _ ⟩ = refl zw-sub x ⟨⟩ = refl zw-sub x (xs ** ys) = cong₂ _**_ (zw-sub x xs) (zw-sub x ys) up-sub : ∀ n (xs : Vec A m) → up (choose n xs) ≡ cmap sub (choose (suc n) xs) up-sub zero xs = choose-prop isProp-[] _ _ up-sub (suc n) [] = refl up-sub (suc n) (x ∷ xs) = cong₂ _**_ (up-sub (suc n) xs) $ zw _∷_ (choose (suc n) xs) (up (cmap (x ∷_) (choose n xs))) ≡⟨ cong (zw _∷_ _) (up-nat (x ∷_) (choose n xs)) ⟩ zw _∷_ (choose (suc n) xs) (cmap (vmap (x ∷_)) (up (choose n xs))) ≡⟨ cong (zw _∷_ _) (cong (cmap (vmap (x ∷_))) (up-sub n xs)) ⟩ zw _∷_ (choose (suc n) xs) (cmap (vmap (x ∷_)) (cmap sub (choose (suc n) xs))) ≡⟨ cong (zw _∷_ _) (cmap-comp _ _ _) ⟩ zw _∷_ (choose (suc n) xs) (cmap (vmap (x ∷_) ∘ sub) (choose (suc n) xs)) ≡˘⟨ zw-sub x (choose (suc n) xs) ⟩ cmap sub (cmap (x ∷_) (choose (suc n) xs)) ∎