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 x
s 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
Post a Comment