# Notes to Algebra of Programming This work is released under the CC0 public domain dedication. See https://creativecommons.org/publicdomain/zero/1.0 for more information. # Chapter 2 ## Exercise 2.4. NTS: f . g = id => g is monic and f is epic. Assume that g is not monic, and let h, i be maps such that g . h = g . i and h /= i But we have that h = id . h = (f . g) . h = f . (g . h) = f . (g . i) = (f . g) . i = id . i = i, a contradiction. Using PEM, g must be monic. Similarly, assume that f is not epic, and let j, k by maps such that j . f = k . f and j /= k But we have that j = j . id = j . (f . g) = (j . f) . g = (k . f) . g = k . (f . g) = k . id = k, a contradiction. Using PEM, f must be monic. Can we prove these results constructively? Yes; here they are. g is monic if g ∘ h = g ∘ i ⇒ h = i for all h, i. Assume that we have h, i such that g ∘ h = g ∘ i. By left-composing both compositions with f, we have f ∘ g ∘ h = f ∘ g ∘ i; then, since f ∘ g = id, we have h = i, as required. f is epic if h ∘ f = i ∘ f ⇒ h = i for all h, i. Assume that we have h, i such that h ∘ f = i ∘ f. By right-composing both compositions with g, we have h ∘ f ∘ g = i ∘ f ∘ g; then, since f ∘ g = id, h = i, as required. ## Ex. 2.5 (a) NTS: If f ∘ g is epic, then f is epic. Let h, i be maps such that h ∘ f = i ∘ f. We must also have that h ∘ f ∘ g = i ∘ f ∘ g, and thus h ∘ id = i ∘ id ≡ h = i, as required. (b) What is the dual statement? Let's construct this carefully. We know that "is epic" is dual to "is monic"; we reverse the composition, and rename the maps for clarity: "If f ∘ g is monic, then g is monic." Proof: Let h, i be maps such that g ∘ h = g ∘ i. Then it also holds that f ∘ g ∘ h = f ∘ g ∘ i, and thus id ∘ h = id ∘ i ≡ h = i, as required. ## Ex. 2.6 A preorder regarded as a category is a thin category (at most one arrow between any two objects), so every arrow is both monic and epic, trivially. Nothing requires that an arrow have an inverse, however (this only happens for objects a, b where a ≤ b and b ≤ a), so not every arrow is an isomorphism. ## Ex. 2.7 (a) A relation ~ : A ← B is *onto* if ∀a ∈ A . ∃b ∈ B. a ~ b. Is every onto arrow in Rel epic? Assume R : A ← B is onto and S, T : C ← A are arrows (in Rel) such that S ∘ R = T ∘ R. By composition of relations, we have (c, b) ∈ (S ∘ R) ⇔ ∃a ∈ A . a `R` b ∧ c `S` a In general, we do not have that S = T. For example, let B = {b}, A = {a, a′}, C = {c}, and let R = {(a, b), (a′, b)}, S = {(c, a)}, and T = {(c, a′)}. Then S ∘ R = T ∘ R, but S ≠ T. If R is a partial function (functional relation), though, then we must have S = T (that is, R is epic). In this case, if there is some (c, b) in both S ∘ R and T ∘ R, then there must be a unique a ∈ A such that (a, b) ∈ R, and thus (c, a) is in S ∘ R and in T ∘ R. Since (c, b) was arbitrary, we have that S = T, as required. (I was misled somewhat by the "partial" terminology.) ## Ex. 2.8 From any category A, we can construct the *Arrow category* Arr(A) whose objects are the morphisms of A. What are the objects? I had to look this one up. It's very interesting; the arrows are pairs of arrows of A describing commuting squares. If A is given by the commuting diagram h i L -----> M -----> R | | | f | | g | j v v v P -----> Q -----> S k l then (h, k) is a morphism of Arr(A) since k ∘ f = g ∘ h, and (i, l) is another, since l ∘ g = j ∘ i. (h,k) (i,l) f -----> g -----> j The composition (i, l) ∘ (h, k) is defined, since j ∘ i ∘ h = l ∘ k ∘ f in A. TODO: Find more about arrow categories. TODO: What are the monic arrows in this category? ## Ex. 2.9 NTS: Functors preserve isomorphisms. Let i : B ← A be an isomorphism with inverse i⁻¹ : A → B in some category C, and let F : C → D be a functor. Since functors preserve the source and target of arrows, we have F(i) : F(B) ← F(A) F(i⁻¹) : F(A) ← F(B) so the types are right. We reason: F(i⁻¹) ∘ F(i) = { functor law } F(i⁻¹ ∘ i) = { inverse } F(id_A) = { functor law } id_(F A), so that F(i) is an isomorphism between F(A) and F(B), as required. ## Ex. 2.10 What is a functor between preorders? This maps a preorder to another preorder with (possibly) different objects but with the same structure; that is, if A ≤ B in a preorder P and F : Q ← P, then F(A) ≤ F(B). ## Ex. 2.11 For a category C, define H(A, B) = { f | f : A ← B in C } H(f, h) g = f ∘ g ∘ h H is a bifunctor which maps a pair of objects to their set of arrows (hom set), and maps a pair of arrows to the function which "bookends" an arrow with them. So the objects of H's codomain category are the hom sets of C. What are the morphisms? The composition law doesn't seem to hold? H(f, g) (H(h, k) i) = H(f, g) (h . i . k) = f . h . i . k . g = (f . h) . i . (k . g) = H(f . h, k . g) i (After doing some searching.) This is because H is contravariant in its first argument and covariant in its second; equivalently, H : Cop × C → Set. H is the "hom bifunctor" of C. ## Ex. 2.12 tree A ::= tip A | bin (tree A, tree A) Considered as a functor, tree : Fun ← Fun takes a set A to the set of binary trees over A. What does it do on morphisms? For f : B ← A, tree f : tree B ← tree A tree f (tip a) = tip (f a) tree f (bin s t) = bin (tree f s) (tree f t) The first functor property, tree id = id, is almost immediate by induction. For the second, we reason as follows. For tips, we have tree (f ∘ g) (tip a) = tip (f (g a)) = tree f (tip (g a)) = (tree f ∘ tree g) (tip a), which establishes the case. For trees of the form (bin s t), assume that the result holds for s and t. Then: tree (f ∘ g) (bin s t) = { tree.2 } bin (tree (f ∘ g) s) (tree (f ∘ g) t) = { hypothesis } bin ((tree f ∘ tree g) s) ((tree f ∘ tree g) t) = { tree.2 } (tree f ∘ tree g) (bin s t) as required. ∎ ## Ex. 2.14 What are the functors in the naturality condition for swap? The equation was (g × f) ∘ swap = swap ∘ (f × g). swap C × A ←—————— A × C | | g × f | | f × g ↓ ↓ D × B ←—————— B × D swap We can describe the (bi)functor on the left side of the diagram as (×′), given by A ×′ B = B × A f ×′ g = g × f So the natural transformation is swap : (_×′_) ← (_×_). ## Ex. 2.15 τ_A : P A ← A τ_A a = {a} NTS: τ is a natural transformation P ← id. For all objects A, B and morphism f : A ← B, does the following commute? τ_A P A ←—————— A | | P f | | f ↓ ↓ P B ←—————— B τ_B Yes, since { f a } and { f x | x ∈ { a } } are the same subsets of B. Do we also have the natural trans. Jτ : JE ← id ? Jτ : JP ← Jid ≡ JP ← J Jτ_A JP A ←—————— J A | | JP f | | J f ↓ ↓ JP B ←—————— J B Jτ_B We know (p. 35) that Jτ is natural, so this commutes. We need to determine whether JP ← J is equivalent to JE ← id. From p. 32, we know that P = EJ. Thus, JP ← J ≡ JEJ ← J ≡η JE ← id, as required. Diagram TODO. ## Ex. 2.16 cp : ∀α . listr (P α) → P (listr α) cp [x₁, x₂, ..., xₙ] = { [a₁, a₂, ..., aₙ] | ∀i ∈ [1, n] : aᵢ ∈ xᵢ } Informally, cp takes a (right) list of subsets of A to the set of lists with elements drawn in order from those subsets. The functors involved are listr P and P listr. cp_A P listr A ←—————— listr P A | | P listr f | | listr P f ↓ ↓ P listr B ←—————— listr P B cp_B Does this commute? For arbitrary f : B ← A and [x₁, x₂, ..., xₙ] ∈ listr (P A), we have P (listr f) (cp [x₁, x₂, ..., xₙ]) = { P on arrows } { listr f as | as ∈ cp [x₁, x₂, ..., xₙ] } = { cp.1 } { listr f as | as ∈ { [a₁, a₂, ..., aₙ] | ∀i ∈ [1, n] : aᵢ ∈ xᵢ } } = { compactify } { listr f [a₁, a₂, ..., aₙ] | ∀i ∈ [1, n] : aᵢ ∈ xᵢ } = { listr f def. } { [f a₁, f a₂, ..., f aₙ] | ∀i ∈ [1, n] : aᵢ ∈ xᵢ } = { naturality of listr, P (TODO: formalize) } { [a₁, a₂, ..., aₙ] | ∀i ∈ [1, n] : aᵢ ∈ ((P f) xᵢ) } = { cp.1 } cp [(P f) x₁, (P f) x₂, ..., (P f) xₙ] = { listr on arrows } cp (listr (P f) [x₁, x₂, ..., xₙ]), as required. This is rather informal. The "TODO" step uses the notion that drawing a list from a collection of sets xss after applying f to all of the elements of those sets is equivalent to drawing a list from the sets xss, then applying listr f to the result. ## Ex. 2.17 φ_HA F A ←—————— G (H A) | | F f | | G (H f) ↓ ↓ F B ←—————— G (H B) φ_HB Clearly φ is a natural trans. of type F ← GH. We also are given that (φH)_A = φ_HA, that is H H A ←————— A | || φ | || ↓ || F A ←————— A φ_HA So we must have that H = GH, and thus H = id. φ ∘ id = φ, so φH is a natural transformation. ## Ex. 2.18 We can generalize listr : Fun ← Fun to a functor Par ← Par by defining (listr f) x = ⊥ if ∃a ∈ x . f x = ⊥ For each set A, we have a morphism head : A ← listr A in Par. Is head a natural transformation id ← listr ? The diagram is head_A A ←——————— listr A | | f | | listr f ↓ ↓ B ←——————— listr B head_B or f ∘ head ≟ head ∘ listr f. Let's assume that we have a list [a₁, a₂] and that f a₁ = b but f a₂ = ⊥. Then f (head [a₁, a₂]) = f a₁ = b but head (listr f [a₁, a₂]) = head ⊥ = ⊥ So the naturality does not hold of head. ## Ex. 2.20 An element of A is an arrow e : A ← 1 (where 1 is a terminal object). (a) NTS: Any element is constant. Let e : A ← 1 be an element and let f, g : 1 ← B be arbitrary arrows. Since 1 is terminal, we must have that f = !_B = g, so e ∘ f = e ∘ g, i.e. e is constant. ∎ (b) NTS: Assuming that B (an object) has at least one element, any constant arrow c : A ← B can be factored as e ∘ !_B for some element e of A. !_B B —————→ 1 || | || | e || ↓ B —————→ A c If we define e = c b, we have a constant arrow e ∘ !_B : A ← B which selects the same element of A as does c. ## Ex. 2.21 An object A is called empty if the only arrows with target A are ¡_A : A ← 0 (where 0 is an initial object) and id_A. The empty object of Fun is the empty set (which is also initial). Similarly for Rel. In Fun × Fun, any object of the form (A × ∅) or (∅ × B) is empty. ## Ex. 2.22 A preorder-as-category with a terminal object has an upper bound, i.e. there is an element e such that a ≤ e for all elements a of the preorder. ## Ex. 2.23 If categories C and D have terminal objects, clearly C × D does as well; for every object (A, B), there is an arrow (!_A, !_B) : (1_C, 1_D) ← (A, B), so (1_C, 1_D) is terminal. Dually, if C and D have initial objects, then for every object (a, b) in C × D there is an arrow (¡_A, ¡_B) : (A, B) ← (0_A, 0_B), so (0_A, 0_B) is initial. ## Ex. 2.24 If C and D (categories) have terminal objects, what is the terminal object in C^D (the category of functors A ← B)? A terminal object in C^D is a functor F1 such that, for any other functor G : C ← D, there is a natural transformation !_G : F1 ← G. We know what kinds of functors have this property; namely, the constant functors: const A A ←—————— G A | | K_A f | | G f ↓ ↓ A ←—————— G B const A So, for any object A ∈ C, the constant functor K_A is terminal. How does this relate to the terminal objects of C and D? ## Ex. 2.25 Products in the category derived from the partial order (ℕ, ≤) correspond to meets. The product m × n gives the meet of m, n, which may here be interpreted as the greatest lower bound. m × n has arrows to both m and n, and, for all p with arrows to m and to n (meaning p ≤ m ∧ p ≤ n in our partial order), we have an arrow m × n ← p (meaning p ≤ glb(m, n)). Dually, coproducts here correspond to joins, which are least upper bounds in the partial order setting. ## Ex. 2.27 Prove the exchange law: ⟨[f, g], [h, k]⟩ = [⟨f, h⟩, ⟨g, k⟩] This must follow from the universal properties of product and coproduct, but here's the straightforward point-wise proof. The types match: f : B ← A g : B ← C h : D ← A k : D ← C -------------------- -------------------- [f, g] : B ← A + C [h, k] : D ← A + C ----------------------------------------------- ⟨[f, g], [h, k]⟩ : B × D ← A + C f : B ← A h : D ← A g : B ← C k : D ← C -------------------- -------------------- ⟨f, h⟩ : B × D ← A ⟨g, k⟩ : B × D ← C ----------------------------------------------- [⟨f, h⟩, ⟨g, k⟩] : B × D ← A + C We can show that the two are equal by case analysis on the A + C argument. Case inl: ⟨[f, g], [h, k]⟩ (inl a) = { split def. } ([f, g] (inl a), [h, k] (inl a)) = { either.1 } (f a, h a) = { split def. } ⟨f, h⟩ a = { either.1 } [⟨f, h⟩, ⟨g, k⟩] (inl a) which establishes the case. Case inr: ⟨[f, g], [h, k]⟩ (inr c) = { split def. } ([f, g] (inr c), [h, k] (inr c)) = { either.2 } (g c, k c) = { split def. } ⟨g, k⟩ c = { either.2 } [⟨f, h⟩, ⟨g, k⟩] (inr c) as required. ∎ ## Ex. 2.28 Let A × B be a product in Fun. The projections outl, outr are epic iff A and B are non-empty (basic set theory), but not in general. For a coproduct A + B, the injections inl, inr are monic regardless of the choice of A and B; each a ∈ will correspond to a single element (inl a) ∈ A + B, and similarly for each b. Does this contradict duality? I'm not entirely sure what this question means. ## Ex. 2.33 What is the initial algebra of the identity functor? id : A ← I A is pretty much the only identity algebra available to us. If f is any I-algebra B ← I B, then we must solve the following for α: ([f]) ∘ α = f ∘ ([f]) Let's assume that A is initial, that α = id, and that ([f]) = ¡_B, the unique morphism B ← A, for any f. This works out type-wise, but does it hold that ¡_B = f ∘ ¡_B for any identity-algebra f? Yes, this makes sense, given what we said about identity algebras. It's a little fuzzy, though. So, if we have a category C with an initial object, then the identity functor I : C ← C has an initial algebra. ## Ex. 2.34 Let α : T ← F T be the initial algebra of F. NTS: If m : T → A and m′ : A → T (for some A) and m′ ∘ m = id_T, then m is a catamorphism. Define f = m ∘ α ∘ F m′. Then, by functorality of F, f ∘ F m = m ∘ α ∘ F m′ ∘ F m = m ∘ α ∘ F (m′ ∘ m) = m ∘ α ∘ F id = m ∘ α ∘ id = m ∘ α, showing that m = ([f]), i.e. m is a catamorphism. ∎ ## Ex. 2.35 NTS: ([f ∘ g]) = f ∘ ([g ∘ F f]). This is basically just a matter of type inference: If f : A → B, then F f : F A → F B. Since both f ∘ g and g ∘ F f are defined, we must have that g : F B → A, so that f ∘ g : F B → B is an F-algebra. Applying cata fusion, we have f ∘ ([g ∘ F f]) = ([h]) ⇐ f ∘ g ∘ F f = h ∘ F f for some F-algebra h : F B → B. This hold for h = f ∘ g. ∎ The diagram makes all of this quite clear, but is hard to textify. ## Ex. 2.36 Let α : T ← F T be the initial algebra of F. NTS: If f : A ← T, then f = outl ∘ ([g]) for some g. Proof: Define ([g]) : A × T ← T ([g]) = ⟨f, id⟩ and define g : A × T ← F (A × T) by the homomorphism equation g ∘ F ([g]) = ([g]) ∘ α Then, by product cancellation, outl ∘ ([g]) = f, as required. ∎ This assumes, of course, that the product A × T is defined. But the proposition makes no sense if it isn't. ## Ex. 2.38 What is the meaning of a type T with a base functor of type F : (D × C) → C ? What is the type of the functor T? Why are the arguments D, C lexically swapped? If T is given by T X = F (X, T X), then we have that T is an endofunctor D → C. Let D = Fun × Fun, C = Fun, and F ((f, g), h) = f + g Given the definitions above, T would be a functor Fun × Fun → Fun; using the definition of type functors (2.13), its behavior on maps is given by T (f, g) = ⦇α ∘ F((f, g), id)⦈ = ⦇α ∘ (f + g)⦈ Can we say more about this type functor? # Chapter 3 ## Ex. 3.1 Let F X = 1 + (N × X). NTS: ⟨[zero, plus] ∘ F outl, [zero, succ ∘ outr] ∘ F outr⟩ = [zeros, pluss] where zeros : A → ⟨ℕ, ℕ⟩ zeros = ⟨zero, zero⟩ (zeros.1) pluss : (ℕ × (ℕ × ℕ)) → ℕ × ℕ pluss (a, (b, n)) = (a + b, n + 1) This is the missing piece in the chapter's example. It is motivated by sum = ⦇[zero, plus]⦈ length = ⦇[zero, succ ∘ outr]⦈ average = div ∘ ⟨sum, length⟩, on which the banana-split theorem yields div ∘ ⟨sum, length⟩ = div ∘ ⦇⟨[zero, plus] ∘ F outl, [zero, succ ∘ outr] ∘ F outr⟩⦈ where F is the base functor above. Though given only implicitly, we know that F f = id + id × f First, we need a point-free def. of pluss: pluss = ⟨plus ∘ (id × outl), succ ∘ outr ∘ outr⟩ (pluss.1) Then, we reason ⟨[zero, plus] ∘ F outl, [zero, succ ∘ outr] ∘ F outr⟩ = { F on arrows } ⟨[zero, plus] ∘ (id + id × outl), [zero, succ ∘ outr] ∘ (id + id × outr)⟩ = { + absorption, id natural } ⟨[zero, plus ∘ (id × outl)], [zero, succ ∘ outr ∘ (id × outr)]⟩ = { × cancellation } ⟨[zero, plus ∘ (id × outl)], [zero, succ ∘ outr ∘ outr]⟩ = { exchange law } [⟨zero, zero⟩, ⟨plus ∘ (id × outl), succ ∘ outr ∘ outr⟩] = { zeros.1, pluss.1 } [zeros, pluss] ∎ ## Ex. 3.2 Let F : C ← C be a functor, where C is a category with products. Define φ = ⟨F outl, F outr⟩. Between what functors is φ a natural transformation? We define the functors G, H by G (f, g) = F (f × g) H (f, g) = F f × F g with the obvious behavior on objects. It is immediate by composition that G is a bifunctor; that H is as well is worth showing: H (id, id) = F id × G id = id × id = id H (f ∘ h, g ∘ k) = { H on arrows } F (f ∘ h) × F (g ∘ k) = { F functor } (F f ∘ F h) × (F g × F k) = { × bifunctor } (F f × F g) ∘ (F h × F k) = { H on arrows } H (f, g) ∘ H (h, k) We have the diagram: φ H(A, B) ←———————— G(A, B) | | H(f, g) | | G(f, g) ↓ ↓ H(C, D) ←———————— G(C, D) φ This commutes, since: H (f, g) ∘ φ = { H on arrows, φ def. } (F f × F g) ∘ ⟨F outl, F outr⟩ = { × absorption } ⟨F f ∘ F outl, F g ∘ F outr⟩ = { F functor } ⟨F (f ∘ outl), F (g ∘ outr)⟩ = { projections/× } ⟨F (outl ∘ (f × g)), F (outr ∘ (f × g))⟩ = { F functor } ⟨F outl ∘ F (f × g), F outr ∘ F (f × g)⟩ = { × fusion } ⟨F outl, F outr⟩ ∘ F (f × g) = { φ def., G on arrows } φ ∘ G (f, g) ## Ex. 3.3 Define a linear-time version of steep nil = true steep (cons (a, x)) = a > sum x ∧ steep x This is a paramorphism. Nothing covered in the book so far gives us a way to reason about these; presumably that's the next exercise. Here's the paramorphism: steep = outr ∘ ⦇[⟨zero, true⟩], f]⦈ f (x, (s, b)) = (x + s, b ∧ (x > s)) It's possible to formulate f point-free, but it's hairy. A simpler paramorphism example would have been nice. ## Ex. 3.4 The solution to this is most of Meertens's _Paramorphisms_ paper. The given condition, g ∘ F ⟨f, ⦇h⦈⟩ = f ∘ α is sufficient to make the "tupled map" ⟨f, ⦇h⦈⟩ identical to the catamorphism ⦇k⦈, where k : F (A × B) → A × B k = ⟨g, h ∘ F outr⟩ The derivation of this property (adapted from Meertens's version): ⟨f, ⦇h⦈⟩ = ⦇⟨g, h ∘ F outr⟩⦈ ≡ { catamorphism def. } ⟨g, h ∘ F outr⟩ ∘ F ⟨f, ⦇h⦈⟩ = ⟨f, ⦇h⦈⟩ ∘ α ≡ { × fusion } ⟨g ∘ F ⟨f, ⦇h⦈⟩, h ∘ F outr ∘ F ⟨f, ⦇h⦈⟩⟩ = ⟨f ∘ α, ⦇h⦈ ∘ α⟩ ≡ { F functor properties } ⟨g ∘ F ⟨f, ⦇h⦈⟩, h ∘ F (outr ∘ ⟨f, ⦇h⦈⟩)⟩ = ⟨f ∘ α, ⦇h⦈ ∘ α⟩ ≡ { catamorphism def. } ⟨g ∘ F ⟨f, ⦇h⦈⟩, h ∘ F (outr ∘ ⟨f, ⦇h⦈⟩)⟩ = ⟨f ∘ α, h ∘ F ⦇h⦈⟩ ≡ { × cancellation } ⟨g ∘ F ⟨f, ⦇h⦈⟩, h ∘ F ⦇h⦈⟩ = ⟨f ∘ α, h ∘ F ⦇h⦈⟩ ≡ { split bijective: ⟨f, g⟩ = ⟨f, h⟩ ⇒ g = h } g ∘ F ⟨f, ⦇h⦈⟩ = f ∘ α It follows that outl ∘ ⦇k⦈ = f. All of this comes from Meertens's paper, which includes several other very interesting results. I was not able to derive k myself, but at least it got me to go make sense of the paper. ## Ex. 3.5 tree A ::= null | node (tree A, A, tree A) Balance condition: [balanced null = true] balanced (node (s, _, t)) = let { n = size s; m = size t } in 1/3 ≤ n/(n + m + 1) ≤ 2/3 ∧ balanced s ∧ balanced t Derive an efficient (paramorphism) implementation. For slightly more symmetry, I'm going to write the base functor of the tree type as F(A, B) = 1 + A × (B × B) F(f, g) = id + f × both g both g = g × g For brevity, F B = F(A, B) F f = F(id, f) balanced has a somewhat torturous point-free definition: balanced ∘ null = true balanced ∘ node = and ∘ ⟨and ∘ (balanced × balanced), in-range ∘ (size × size)⟩ ∘ outr in-range : ℕ × ℕ → Bool in-range = and ∘ ⟨ge-1/3, le-2/3⟩ ∘ div ∘ ⟨outl, succ ∘ plus⟩ ge-1/3 = ≥ ∘ ⟨id, const 1/3⟩ le-2/3 = ≤ ∘ ⟨id, const 2/3⟩ First of all, we need the size function, defined directly by size : T A → ℕ size ∘ null = zero size ∘ node = succ ∘ plus ∘ (size × size) ∘ outr (i.e. size (a, (s, t)) = 1 + size s + size t in pointwise terms.) Clearly this is a catamorphism: α T A ←———————— F (T A) | | ⦇ψ⦈ = size | | F ⦇ψ⦈ ↓ ↓ ℕ ←—————————— F ℕ ψ The catamorphism universal property and the definition of the initial algebra α gives us the equations: size ∘ null = ψ ∘ F size ∘ inl size ∘ node = ψ ∘ F size ∘ inr The solution to the first: size ∘ null = ψ ∘ F size ∘ inl ≡ { size.1, F def. } zero = ψ ∘ (id + id × (size × size)) ∘ inl ≡ { + cancellation, id } zero = ψ ∘ inl The second: size ∘ node = ψ ∘ F size ∘ inr ≡ { size.2, F def. } succ ∘ plus ∘ (size × size) ∘ outr = ψ ∘ (id + id × (size × size)) ∘ inr ≡ { + cancellation, id } succ ∘ plus ∘ (size × size) ∘ outr = ψ ∘ inr ∘ id × (size × size) ≡ { f ∘ outr = outr ∘ (g ∘ f) for all well-typed f, g } succ ∘ plus ∘ outr ∘ id × (size × size) = ψ ∘ inr ∘ id × (size × size) ≡ { cong } succ ∘ plus ∘ outr = ψ ∘ inr So we have size = ⦇ψ⦈ = ⦇[zero, succ ∘ plus ∘ outr]⦈ Now we can work on balanced. α T A ←———————— F (T A) | | balanced | | F ⟨balanced, ⦇ψ⦈⟩ ↓ ↓ 2 ←——————— F (2 × ℕ) φ We define (using Meertens's para-brackets): balanced = ⟦φ⟧ = outl ∘ ⦇χ⦈ χ = ⟨φ, ψ ∘ F outr⟩ We've already derived ψ, so now we need to define φ. Following the structure of F, we have two equations. The first is solved quickly: φ ∘ F ⟨balanced, ⦇ψ⦈⟩ ∘ inl = balanced ∘ [null, node] ∘ inl ≡ { + cancellation, F def. } φ ∘ id + id × both ⟨balanced, ⦇ψ⦈⟩ ∘ inl = balanced ∘ null ≡ { + cancellation } φ ∘ inl ∘ id = balanced ∘ null ≡ { id/∘, balanced.1 } φ ∘ inl = true The second: balanced ∘ [null, node] ∘ inr = φ ∘ F ⟨balanced, ⦇ψ⦈⟩ ∘ inr ≡ { F def., + cancellation (both sides) } balanced ∘ node = φ ∘ inr ∘ id × both ⟨balanced, ⦇ψ⦈⟩ ≡ { balanced.2 } and ∘ ⟨and ∘ both balanced), in-range ∘ both size⟩ ∘ outr = φ ∘ inr ∘ id × both ⟨balanced, ⦇ψ⦈⟩ ≡ { × absorption } and ∘ and × in-range ∘ ⟨both balanced, both size⟩ ∘ outr = φ ∘ inr ∘ id × both ⟨balanced, ⦇ψ⦈⟩ ≡ { f ∘ outr = outr ∘ (g ∘ f) } and ∘ and × in-range ∘ outr ∘ id × ⟨both balanced, both size⟩ = φ ∘ inr ∘ id × both ⟨balanced, ⦇ψ⦈⟩ ≡ { define trans = ⟨⟨outl ∘ outl, outl ∘ outr⟩, ⟨outr ∘ outl, outr ∘ outr⟩⟩ } and ∘ and × in-range ∘ outr ∘ id × trans ∘ id × both ⟨balanced, size⟩ = φ ∘ inr ∘ id × both ⟨balanced, ⦇ψ⦈⟩ ≡ { ⦇ψ⦈ = size } and ∘ and × in-range ∘ outr ∘ id × trans ∘ id × both ⟨balanced, ⦇ψ⦈⟩ = φ ∘ inr ∘ id × both ⟨balanced, ⦇ψ⦈⟩ ≡ { × cancellation } and ∘ and × in-range ∘ trans ∘ outr ∘ id × both ⟨balanced, ⦇ψ⦈⟩ = φ ∘ inr ∘ id × both ⟨balanced, ⦇ψ⦈⟩ ≡ { cong. } and ∘ and × in-range ∘ trans ∘ outr = φ ∘ inr Putting both together (via the universal property of +), we have φ = [true, and ∘ and × in-range ∘ trans ∘ outr] We have a solution for χ, which we simplify: χ = ⟨[true, and ∘ and × in-range ∘ trans ∘ outr], [zero, succ ∘ plus ∘ outr] ∘ F outr⟩ = { F def. } ⟨[true, and ∘ and × in-range ∘ trans ∘ outr], [zero, succ ∘ plus ∘ outr] ∘ id + id × both outr⟩ = { + absorption, id/∘ } ⟨[true, and ∘ and × in-range ∘ trans ∘ outr], [zero, succ ∘ plus ∘ outr ∘ id × both outr]⟩ = { exchange } [⟨true, zero⟩, ⟨and ∘ and × in-range ∘ trans ∘ outr, succ ∘ plus ∘ outr ∘ id × both outr⟩] = { × cancellation } [⟨true, zero⟩, ⟨and ∘ and × in-range ∘ trans ∘ outr, succ ∘ plus ∘ both outr ∘ outr⟩] In pointwise terms, χ null = (True, 0) χ (node a (b, n) (c, m)) = (b ∧ c ∧ in-range n m, n + m + 1) ## Ex. 3.6 Write preds as a paramorphism. preds : ℕ → list ℕ preds n = [n, n - 1, ..., 1] We define preds recursively by preds ∘ zero = null preds ∘ succ = cons ∘ ⟨succ, preds⟩ The base functor is given by F A = 1 + A F f = id + f It has the initial algebra α : F ℕ → ℕ α = [zero, succ] The diagram: α ℕ ←—————————— F ℕ | | preds | | F ⟨preds, ⦇ψ⦈⟩ ↓ ↓ list ℕ ←——— F (list ℕ × ℕ) φ The types above give us ψ : F ℕ → ℕ If we can define φ and ψ such that the above commutes, then, by the universal property of paramorphism, we'll have preds = outl ∘ ⦇ψ⦈ χ = ⟨φ, ψ ∘ F outr⟩ As a diagram, α ℕ ←—————————— F ℕ | | ⦇χ⦈ | | F ⦇χ⦈ ↓ ↓ list ℕ × ℕ ←— F (list ℕ × ℕ) | χ ‖ outl | ‖ ↓ ‖ list ℕ ←————— F (list ℕ × ℕ) φ We calculate from the left disjunct: φ ∘ F ⟨preds, ⦇ψ⦈⟩ ∘ inl = preds ∘ α ∘ inl ≡ { α def., + cancellation } φ ∘ F ⟨preds, ⦇ψ⦈⟩ ∘ inl = preds ∘ zero ≡ { F def. } φ ∘ id + ⟨preds, ⦇ψ⦈⟩ ∘ inl = preds ∘ zero ≡ { + cancellation, id/∘ } φ ∘ inl = preds ∘ zero ≡ { preds.1 } φ ∘ inl = null which gives the first disjunct of φ. The second: φ ∘ F ⟨preds, ⦇ψ⦈⟩ ∘ inr = preds ∘ α ∘ inr ≡ { α def., + cancellation } φ ∘ F ⟨preds, ⦇ψ⦈⟩ ∘ inr = preds ∘ succ ≡ { F def. } φ ∘ id + ⟨preds, ⦇ψ⦈⟩ ∘ inr = preds ∘ succ ≡ { + cancellation } φ ∘ inr ∘ ⟨preds, ⦇ψ⦈⟩ = preds ∘ succ ≡ { preds.2 } φ ∘ inr ∘ ⟨preds, ⦇ψ⦈⟩ = cons ∘ ⟨succ, preds⟩ ≡ { flip ≡df outr × outl } φ ∘ inr ∘ ⟨preds, ⦇ψ⦈⟩ = cons ∘ flip ∘ ⟨preds, succ⟩ ≡ { provisionally define ⦇ψ⦈ = succ } φ ∘ inr ∘ ⟨preds, ⦇ψ⦈⟩ = cons ∘ flip ∘ ⟨preds, ⦇ψ⦈⟩ ≡ { cong. } φ ∘ inr = cons ∘ flip I believe that we can generalize ψ to α. We have calculated φ = [null, cons ∘ flip] ψ = α and of course ⦇ψ⦈ = ⦇α⦈ = id. So: χ = ⟨φ, α ∘ F outr⟩ = ⟨[null, cons ∘ flip], [zero, succ] ∘ F outr⟩ = { F def. } ⟨[null, cons ∘ flip], [zero, succ] ∘ id + outr⟩ = { + absorption, id/∘ } ⟨[null, cons ∘ flip], [zero, succ ∘ outr]⟩ = { exchange } [⟨null, zero⟩, ⟨cons ∘ flip, succ ∘ outr⟩] and thus preds = outl ∘ ⦇[⟨null, zero⟩, ⟨cons ∘ flip, succ ∘ outr⟩]⦈ This completes the synthesis of the paramorphic version of preds.