Arity-generic programming in Agda -


how write arity-generic functions in agda? possible write dependent , universe polymorphic arity-generic functions?

i'll take n-ary composition function example.

the simplest version

open import data.vec.n-ary  comp : ∀ n {α β γ} {x : set α} {y : set β} {z : set γ}      -> (y -> z) -> n-ary n x y -> n-ary n x z comp  0      g y = {!!} comp (suc n) g f = {!!} 

here how n-ary defined in data.vec.n-ary module:

n-ary : ∀ {ℓ₁ ℓ₂} (n : ℕ) → set ℓ₁ → set ℓ₂ → set (n-ary-level ℓ₁ ℓ₂ n) n-ary 0    b = b n-ary (suc n) b = → n-ary n b 

i.e. comp receives number n, function g : y -> z , function f, has arity n , resulting type y.

in comp 0 g y = {!!} case have

goal : z y    : y g    : y -> z 

hence hole can filled g y.

in comp (suc n) g f = {!!} case, n-ary (suc n) x y reduces x -> n-ary n x y , n-ary (suc n) x z reduces x -> n-ary n x z. have

goal : x -> n-ary n x z f    : x -> n-ary n x y g    : y -> z 

c-c c-r reduces hole λ x -> {!!}, , goal : n-ary n x z, can filled comp n g (f x). whole definition is

comp : ∀ n {α β γ} {x : set α} {y : set β} {z : set γ}      -> (y -> z) -> n-ary n x y -> n-ary n x z comp  0      g y = g y comp (suc n) g f = λ x -> comp n g (f x) 

i.e. comp receives n arguments of type x, applies f them , applies g result.

the simplest version dependent g

when g has type (y : y) -> z y

comp : ∀ n {α β γ} {x : set α} {y : set β} {z : y -> set γ}      -> ((y : y) -> z y) -> (f : n-ary n x y) -> {!!} comp  0      g y = g y comp (suc n) g f = λ x -> comp n g (f x) 

what should there in hole? can't use n-ary n x z before, because z function now. if z function, need apply something, has type y. way of type y apply f n arguments of type x. our comp @ type level:

comp : ∀ n {α β γ} {x : set α} {y : set β}      -> (y -> set γ) -> n-ary n x y -> set (n-ary-level α γ n) comp  0      z y = z y comp (suc n) z f = ∀ x -> comp n z (f x) 

and comp is

comp : ∀ n {α β γ} {x : set α} {y : set β} {z : y -> set γ}      -> ((y : y) -> z y) -> (f : n-ary n x y) -> comp n z f comp  0      g y = g y comp (suc n) g f = λ x -> comp n g (f x) 

a version arguments different types

there "arity-generic datatype-generic programming" paper, describes, among other things, how write arity-generic functions, receive arguments of different types. idea pass vector of types parameter , fold pretty in style of n-ary:

arrty : {n : n} → vec set (suc n) → set arrty {0}     (a :: []) = arrty {suc n} (a :: as) = → arrty 

however agda unable infer vector, if provide length. hence paper provides operator currying, makes function, explicitly receives vector of types, function, receives n implicit arguments.

this approach works, doesn't scale universe polymorphic functions. can avoid these problems replacing vec datatype _^_ operator:

_^_ : ∀ {α} -> set α -> ℕ -> set α ^ 0     = lift ⊤ ^ suc n = × ^ n 

a ^ n isomorphic vec n. our new n-ary is

_->ⁿ_ : ∀ {n} -> set ^ n -> set -> set _->ⁿ_ {0}      _      b = b _->ⁿ_ {suc _} (a , r) b = -> r ->ⁿ b 

all types lie in set simplicity. comp is

comp : ∀ n {xs : set ^ n} {y z : set}      -> (y -> z) -> (xs ->ⁿ y) -> xs ->ⁿ z comp  0      g y = g y comp (suc n) g f = λ x -> comp n g (f x) 

and version dependent g:

comp : ∀ n {xs : set ^ n} {y : set}      -> (y -> set) -> (xs ->ⁿ y) -> set comp  0      z y = z y comp (suc n) z f = ∀ x -> comp n z (f x)  comp : ∀ n {xs : set ^ n} {y : set} {z : y -> set}      -> ((y : y) -> z y) -> (f : xs ->ⁿ y) -> comp n z f comp  0      g y = g y comp (suc n) g f = λ x -> comp n g (f x) 

fully dependent , universe polymorphic comp

the key idea represent vector of types nested dependent pairs:

sets : ∀ {n} -> (αs : level ^ n) -> ∀ β -> set (mono-^ (map lsuc) αs ⊔ⁿ lsuc β) sets {0}      _       β = set β sets {suc _} (α , αs) β = Σ (set α) λ x -> x -> sets αs β 

the second case reads "there type x such other types depend on element of x". our new n-ary trivial:

fold : ∀ {n} {αs : level ^ n} {β} -> sets αs β -> set (αs ⊔ⁿ β) fold {0}      y      = y fold {suc _} (x , f) = (x : x) -> fold (f x) 

an example:

postulate   explicit-replicate : (a : set) -> (n : ℕ) -> -> vec n  test : fold (set , λ -> ℕ , λ n -> , λ _ -> vec n)  test = explicit-replicate 

but types of z , g now?

comp : ∀ n {β γ} {αs : level ^ n} {xs : sets αs β} {z : {!!}}      -> {!!} -> (f : fold xs) -> comp n z f comp  0      g y = g y comp (suc n) g f = λ x -> comp n g (f x) 

recall f had type xs ->ⁿ y, y hidden in end of these nested dependent pairs , can depend on element of x xs. z had type y -> set γ, hence need append set γ xs, making xs implicit:

_⋯>ⁿ_ : ∀ {n} {αs : level ^ n} {β γ}       -> sets αs β -> set γ -> set (αs ⊔ⁿ β ⊔ γ) _⋯>ⁿ_ {0}      y      z = y -> z _⋯>ⁿ_ {suc _} (_ , f) z = ∀ {x} -> f x ⋯>ⁿ z 

ok, z : xs ⋯>ⁿ set γ, type has g? (y : y) -> z y. again need append nested dependent pairs, since y again hidden, in dependent way now:

Πⁿ : ∀ {n} {αs : level ^ n} {β γ}    -> (xs : sets αs β) -> (xs ⋯>ⁿ set γ) -> set (αs ⊔ⁿ β ⊔ γ) Πⁿ {0}      y      z = (y : y) -> z y Πⁿ {suc _} (_ , f) z = ∀ {x} -> Πⁿ (f x) z 

and finally

comp : ∀ n {αs : level ^ n} {β γ} {xs : sets αs β}      -> (xs ⋯>ⁿ set γ) -> fold xs -> set (αs ⊔ⁿ γ) comp  0      z y = z y comp (suc n) z f = ∀ x -> comp n z (f x)  comp : ∀ n {β γ} {αs : level ^ n} {xs : sets αs β} {z : xs ⋯>ⁿ set γ}      -> Πⁿ xs z -> (f : fold xs) -> comp n z f comp  0      g y = g y comp (suc n) g f = λ x -> comp n g (f x) 

a test:

length : ∀ {α} {a : set α} {n} -> vec n -> ℕ length {n = n} _ = n  explicit-replicate : (a : set) -> (n : ℕ) -> -> vec n explicit-replicate _ _ x = replicate x  foo : (a : set) -> ℕ -> -> ℕ foo = comp 3 length explicit-replicate  test : foo bool 5 true ≡ 5 test = refl 

note dependency in arguments , resulting type of explicit-replicate. besides, set lies in set₁, while , a lie in set — illustrates universe polymorphism.

remarks

afaik, there no comprehensible theory implicit arguments, don't know, how stuff work, when second function (i.e. f) receives implicit arguments. test:

foo' : ∀ {α} {a : set α} -> ℕ -> -> ℕ foo' = comp 2 length (λ n -> replicate {n = n})  test' : foo' 5 true ≡ 5 test' = refl 

is passed @ least.

comp can't handle functions, if universe, type lies, depends on value. example

explicit-replicate' : ∀ α -> (a : set α) -> (n : ℕ) -> -> vec n explicit-replicate' _ _ _ x = replicate x  ... because result in invalid use of setω ... error : ∀ α -> (a : set α) -> ℕ -> -> ℕ error = comp 4 length explicit-replicate' 

but it's common agda, e.g. can't apply explicit id itself:

idₑ : ∀ α -> (a : set α) -> -> idₑ _ _ x = x  -- ... because result in invalid use of setω ... error = idₑ _ _ idₑ 

the code.


Comments

Popular posts from this blog

java - Could not locate OpenAL library -

c++ - Delete matches in OpenCV (Keypoints and descriptors) -

sorting - opencl Bitonic sort with 64 bits keys -