← Back

Modules

Leios

  • Abstract
  • Base
  • Blocks
  • Config
  • Defaults
  • FFD
  • Foreign.BaseTypes
  • Foreign.HsTypes
  • Foreign.Types
  • Foreign.Util
  • KeyRegistration
  • Network
  • Prelude
  • Protocol
  • Short
  • Short.Decidable
  • Short.Trace.Verifier
  • Short.Trace.Verifier.Test
  • Simplified
  • Simplified.Deterministic
  • SpecStructure
  • Traces
  • Voting
  • VRF
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
------------------------------------------------------------------------
-- The Agda standard library
--
-- Nondependent heterogeneous N-ary products
------------------------------------------------------------------------
 
{-# OPTIONS --cubical-compatible --safe #-}
 
module Data.Product.Nary.NonDependent where
 
------------------------------------------------------------------------
-- Concrete examples can be found in README.Nary. This file's comments
-- are more focused on the implementation details and the motivations
-- behind the design decisions.
------------------------------------------------------------------------
 
open import Level using (Level)
open import Agda.Builtin.Unit
open import Data.Product.Base as Prod
import Data.Product.Properties as Prodₚ
open import Data.Sum.Base using (_⊎_)
open import Data.Nat.Base using (ℕ; zero; suc; pred)
open import Data.Fin.Base using (Fin; zero; suc)
open import Function.Base using (const; _∘′_; _∘_)
open import Relation.Nullary.Decidable.Core using (Dec; yes; no; _×-dec_)
open import Relation.Binary.Core using (Rel)
open import Relation.Binary.PropositionalEquality.Core using (_≡_; refl; cong₂)
 
open import Function.Nary.NonDependent.Base
 
-- Provided n Levels and a corresponding "vector" of `n` Sets, we can
-- build a big right-nested product type packing a value for each one
-- of these Sets.
-- We have two distinct but equivalent definitions:
-- the first which is always ⊤-terminated
-- the other which has a special case for n = 1 because we want our
-- `(un)curryₙ` functions to work for user-written functions and
-- products and they rarely are ⊤-terminated.
 
Product⊤ : ∀ n {ls} → Sets n ls → Set (⨆ n ls)
Product⊤ zero as = ⊤
Product⊤ (suc n) (a , as) = a × Product⊤ n as
 
Product : ∀ n {ls} → Sets n ls → Set (⨆ n ls)
Product 0 _ = ⊤
Product 1 (a , _) = a
Product (suc n) (a , as) = a × Product n as
 
-- Pointwise lifting of a relation on products
 
Allₙ : (∀ {a} {A : Set a} → Rel A a) →
∀ n {ls} {as : Sets n ls} (l r : Product n as) → Sets n ls
Allₙ R 0 l r = _
Allₙ R 1 a b = R a b , _
Allₙ R (suc n@(suc _)) (a , l) (b , r) = R a b , Allₙ R n l r
 
Equalₙ : ∀ n {ls} {as : Sets n ls} (l r : Product n as) → Sets n ls
Equalₙ = Allₙ _≡_
 
------------------------------------------------------------------------
-- Generic Programs
 
-- Once we have these type definitions, we can write generic programs
-- over them. They will typically be split into two or three definitions:
 
-- 1. action on the vector of n levels (if any)
-- 2. action on the corresponding vector of n Sets
-- 3. actual program, typed thank to the function defined in step 2.
------------------------------------------------------------------------
 
-- see Relation.Binary.PropositionalEquality for congₙ and substₙ, two
-- equality-related generic programs.
 
------------------------------------------------------------------------
-- equivalence of Product and Product⊤
 
toProduct : ∀ n {ls} {as : Sets n ls} → Product⊤ n as → Product n as
toProduct 0 _ = _
toProduct 1 (v , _) = v
toProduct (suc n@(suc _)) (v , vs) = v , toProduct n vs
 
toProduct⊤ : ∀ n {ls} {as : Sets n ls} → Product n as → Product⊤ n as
toProduct⊤ 0 _ = _
toProduct⊤ 1 v = v , _
toProduct⊤ (suc n@(suc _)) (v , vs) = v , toProduct⊤ n vs
 
------------------------------------------------------------------------
-- (un)curry
 
-- We start by defining `curryₙ` and `uncurryₙ` converting back and forth
-- between `A₁ → ⋯ → Aₙ → B` and `(A₁ × ⋯ × Aₙ) → B` by induction on `n`.
 
curryₙ : ∀ n {ls} {as : Sets n ls} {r} {b : Set r} →
(Product n as → b) → as ⇉ b
curryₙ 0 f = f _
curryₙ 1 f = f
curryₙ (suc n@(suc _)) f = curryₙ n ∘′ curry f
 
uncurryₙ : ∀ n {ls} {as : Sets n ls} {r} {b : Set r} →
as ⇉ b → (Product n as → b)
uncurryₙ 0 f = const f
uncurryₙ 1 f = f
uncurryₙ (suc n@(suc _)) f = uncurry (uncurryₙ n ∘′ f)
 
-- Variants for Product⊤
 
curry⊤ₙ : ∀ n {ls} {as : Sets n ls} {r} {b : Set r} →
(Product⊤ n as → b) → as ⇉ b
curry⊤ₙ zero f = f _
curry⊤ₙ (suc n) f = curry⊤ₙ n ∘′ curry f
 
uncurry⊤ₙ : ∀ n {ls} {as : Sets n ls} {r} {b : Set r} →
as ⇉ b → (Product⊤ n as → b)
uncurry⊤ₙ zero f = const f
uncurry⊤ₙ (suc n) f = uncurry (uncurry⊤ₙ n ∘′ f)
 
------------------------------------------------------------------------
-- decidability
 
Product⊤-dec : ∀ n {ls} {as : Sets n ls} → Product⊤ n (Dec <$> as) → Dec (Product⊤ n as)
Product⊤-dec zero _ = yes _
Product⊤-dec (suc n) (p? , ps?) = p? ×-dec Product⊤-dec n ps?
 
Product-dec : ∀ n {ls} {as : Sets n ls} → Product n (Dec <$> as) → Dec (Product n as)
Product-dec 0 _ = yes _
Product-dec 1 p? = p?
Product-dec (suc n@(suc _)) (p? , ps?) = p? ×-dec Product-dec n ps?
 
------------------------------------------------------------------------
-- pointwise liftings
 
toEqualₙ : ∀ n {ls} {as : Sets n ls} {l r : Product n as} →
l ≡ r → Product n (Equalₙ n l r)
toEqualₙ 0 eq = _
toEqualₙ 1 eq = eq
toEqualₙ (suc n@(suc _)) eq = Prod.map₂ (toEqualₙ n) (Prodₚ.,-injective eq)
 
fromEqualₙ : ∀ n {ls} {as : Sets n ls} {l r : Product n as} →
Product n (Equalₙ n l r) → l ≡ r
fromEqualₙ 0 eq = refl
fromEqualₙ 1 eq = eq
fromEqualₙ (suc n@(suc _)) eq = uncurry (cong₂ _,_) (Prod.map₂ (fromEqualₙ n) eq)
 
------------------------------------------------------------------------
-- projection of the k-th component
 
-- To know at which Set level the k-th projection out of an n-ary
-- product lives, we need to extract said level, by induction on k.
 
Levelₙ : ∀ {n} → Levels n → Fin n → Level
Levelₙ (l , _) zero = l
Levelₙ (_ , ls) (suc k) = Levelₙ ls k
 
-- Once we have the Sets used in the product, we can extract the one we
-- are interested in, once more by induction on k.
 
Projₙ : ∀ {n ls} → Sets n ls → ∀ k → Set (Levelₙ ls k)
Projₙ (a , _) zero = a
Projₙ (_ , as) (suc k) = Projₙ as k
 
-- Finally, provided a Product of these sets, we can extract the k-th
-- value. `projₙ` takes both `n` and `k` explicitly because we expect
-- the user will be using a concrete `k` (potentially manufactured
-- using `Data.Fin`'s `#_`) and it will not be possible to infer `n`
-- from it.
 
projₙ : ∀ n {ls} {as : Sets n ls} k → Product n as → Projₙ as k
projₙ 1 zero v = v
projₙ (suc n@(suc _)) zero (v , _) = v
projₙ (suc n@(suc _)) (suc k) (_ , vs) = projₙ n k vs
projₙ 1 (suc ()) v
 
------------------------------------------------------------------------
-- zip
 
zipWith : ∀ n {lsa lsb lsc}
{as : Sets n lsa} {bs : Sets n lsb} {cs : Sets n lsc} →
(∀ k → Projₙ as k → Projₙ bs k → Projₙ cs k) →
Product n as → Product n bs → Product n cs
zipWith 0 f _ _ = _
zipWith 1 f v w = f zero v w
zipWith (suc n@(suc _)) f (v , vs) (w , ws) =
f zero v w , zipWith n (λ k → f (suc k)) vs ws
 
------------------------------------------------------------------------
-- removal of the k-th component
 
Levelₙ⁻ : ∀ {n} → Levels n → Fin n → Levels (pred n)
Levelₙ⁻ (_ , ls) zero = ls
Levelₙ⁻ {suc (suc _)} (l , ls) (suc k) = l , Levelₙ⁻ ls k
Levelₙ⁻ {1} _ (suc ())
 
Removeₙ : ∀ {n ls} → Sets n ls → ∀ k → Sets (pred n) (Levelₙ⁻ ls k)
Removeₙ (_ , as) zero = as
Removeₙ {suc (suc _)} (a , as) (suc k) = a , Removeₙ as k
Removeₙ {1} _ (suc ())
 
removeₙ : ∀ n {ls} {as : Sets n ls} k →
Product n as → Product (pred n) (Removeₙ as k)
removeₙ (suc zero) zero _ = _
removeₙ (suc (suc _)) zero (_ , vs) = vs
removeₙ (suc (suc zero)) (suc k) (v , _) = v
removeₙ (suc (suc (suc _))) (suc k) (v , vs) = v , removeₙ _ k vs
removeₙ (suc zero) (suc ()) _
 
------------------------------------------------------------------------
-- insertion of a k-th component
 
Levelₙ⁺ : ∀ {n} → Levels n → Fin (suc n) → Level → Levels (suc n)
Levelₙ⁺ ls zero l⁺ = l⁺ , ls
Levelₙ⁺ {suc _} (l , ls) (suc k) l⁺ = l , Levelₙ⁺ ls k l⁺
Levelₙ⁺ {0} _ (suc ())
 
Insertₙ : ∀ {n ls l⁺} → Sets n ls → ∀ k (a⁺ : Set l⁺) → Sets (suc n) (Levelₙ⁺ ls k l⁺)
Insertₙ as zero a⁺ = a⁺ , as
Insertₙ {suc _} (a , as) (suc k) a⁺ = a , Insertₙ as k a⁺
Insertₙ {zero} _ (suc ()) _
 
insertₙ : ∀ n {ls l⁺} {as : Sets n ls} {a⁺ : Set l⁺} k (v⁺ : a⁺) →
Product n as → Product (suc n) (Insertₙ as k a⁺)
insertₙ 0 zero v⁺ vs = v⁺
insertₙ (suc n) zero v⁺ vs = v⁺ , vs
insertₙ 1 (suc k) v⁺ vs = vs , insertₙ 0 k v⁺ _
insertₙ (suc n@(suc _)) (suc k) v⁺ (v , vs) = v , insertₙ n k v⁺ vs
insertₙ 0 (suc ()) _ _
 
------------------------------------------------------------------------
-- update of a k-th component
 
Levelₙᵘ : ∀ {n} → Levels n → Fin n → Level → Levels n
Levelₙᵘ (_ , ls) zero lᵘ = lᵘ , ls
Levelₙᵘ (l , ls) (suc k) lᵘ = l , Levelₙᵘ ls k lᵘ
 
Updateₙ : ∀ {n ls lᵘ} (as : Sets n ls) k (aᵘ : Set lᵘ) → Sets n (Levelₙᵘ ls k lᵘ)
Updateₙ (_ , as) zero aᵘ = aᵘ , as
Updateₙ (a , as) (suc k) aᵘ = a , Updateₙ as k aᵘ
 
updateₙ : ∀ n {ls lᵘ} {as : Sets n ls} k {aᵘ : _ → Set lᵘ} (f : ∀ v → aᵘ v)
(vs : Product n as) → Product n (Updateₙ as k (aᵘ (projₙ n k vs)))
updateₙ 1 zero f v = f v
updateₙ (suc (suc _)) zero f (v , vs) = f v , vs
updateₙ (suc n@(suc _)) (suc k) f (v , vs) = v , updateₙ n k f vs
updateₙ 1 (suc ()) _ _
 
updateₙ′ : ∀ n {ls lᵘ} {as : Sets n ls} k {aᵘ : Set lᵘ} (f : Projₙ as k → aᵘ) →
Product n as → Product n (Updateₙ as k aᵘ)
updateₙ′ n k = updateₙ n k