Reputation: 8423
I'm using Descriptions, like they are described here, as a way of encoding the shape of inductive data types. However, I'm stuck on how to represent inductive types that are:
For example, suppose we've got something like this, where we're ordering different types:
data Foo : Set where
N : ℕ -> Foo
P : (Foo × Foo) -> Foo
data <N : ℕ -> ℕ -> Set where
<0 : (n : ℕ) -> <N zero n
<suc : (m n : ℕ) -> <N m n -> <N (suc m) (suc n)
data <P : (Foo × Foo) -> (Foo × Foo) -> Set
data <F : Foo -> Foo -> Set
data <P where
<Pair : (x1 x2 y1 y2 : Foo) -> <F x1 y1 -> <F x2 y2 -> <P (x1 , x2) (y1 , y2)
data <F where
<FN : ∀ (a b : ℕ) -> <N a b -> <F (N a) (N b)
<FP : ∀ (p1 p2 : (Foo × Foo) ) -> <P p1 p2 -> <F (P p1) (P p2)
That is, we've got a type of binary trees with nats at the leaves. We have a partial order between trees, where we compare nats in the usual way, and we compare pairs of nodes by comparing their respective subtrees.
Notice how <F
and <P
are mutually dependent on each other. Of course, we could inline this to make <F
and <P
one type, I'm trying to avoid that, for cases where <P
is more complicated.
What I'm wondering is: can the above partial order types be expressed using Descriptions?
I get stuck even trying to describe the above types as the fixed-point of an indexed functor. Usually we have an index type (I : Set)
and the functor has type (X : I -> Set) -> I -> Set
. But we can't have both "Foo" and "Foo × Foo" be our I value. Is there some trick that allows us to use
I = Foo ⊎ (Foo × Foo)
?
Upvotes: 2
Views: 125
Reputation: 30103
Take the sum of all of the indices:
Ix = ((Foo × Foo) × (Foo × Foo)) ⊎ (Foo × Foo)
data <P : Ix -> Set
data <F : Ix -> Set
data <P where
<Pair : (x1 x2 y1 y2 : Foo) -> <F (inj₂(x1 , y1)) -> <F (inj₂(x2 , y2))
-> <P (inj₁((x1 , x2), (y1 , y2)))
data <F where
<FN : ∀ (a b : ℕ) -> <N a b -> <F (inj₂(N a , N b))
<FP : ∀ (p1 p2 : (Foo × Foo) ) -> <P (inj₁(p1 , p2)) -> <F (inj₂(P p1 , P p2))
We can tidy up the indices a bit more, and write things in a form which is more obviously describable by indexed functors:
data Ix : Set where
<P : Foo × Foo → Foo × Foo → Ix
<F : Foo → Foo → Ix
data T : Ix → Set where
<Pair : ∀ x1 x2 y1 y2 → T (<F x1 y1) → T (<F x2 y2)
→ T (<P (x1 , x2) (y1 , y2))
<FN : ∀ (a b : ℕ) → <N a b → T (<F (N a) (N b))
<FP : ∀ p1 p2 → T (<P p1 p2) → T (<F (P p1) (P p2))
I note though that <P
and <F
can be defined recursively, so induction is not essential here.
<F : Foo → Foo → Set
<F (N n) (N n') = <N n n'
<F (P (x , y)) (P (x' , y')) = <F x x' × <F y y'
<F (N _) (P _) = ⊥
<F (P _) (N _) = ⊥
Upvotes: 2