module Coalgebras where open import Data.Nat.Base open import Data.Nat.DivMod open import Data.Fin using (Fin; zero; suc) -- Coalgebras in Agda -- Given a functor F, an F-coalgebra is an object S with a morphism -- t : S → F S. -- A typical interpretation would be S is the set of states and -- t is the transition function which takes us from a state s : S -- to (t s), which can, depending on F, do some input and/or output -- and take us (non-deterministically) to a next state or terminate. -- Examples for coalgebras: -- -- F S = Bool × (A → S) automaton accepting A-words (True = accepting state) -- F S = A × S output automaton, generating a stream of outputs of type A -- F S = 1 + A × S output automaton, generating a possibly infinite sequence -- -- Pr S = probability distribution over S -- F S = A → Pr S -- The functor generating lists. data ListF A S : Set where nil : ListF A S cons : A → S → ListF A S mapF : ∀{A S T} (f : S → T) → ListF A S → ListF A T mapF f nil = nil mapF f (cons a s) = cons a (f s) -- Example: Automaton that outputs Collatz sequence starting with n -- n --> n/2 if n is even -- n --> 3n+1 if n is odd collatzStep : ℕ → ListF ℕ ℕ collatzStep 1 = nil collatzStep n with n divMod 2 collatzStep n | result q zero _ = cons n q collatzStep n | result _ _ _ = cons n (1 + 3 * n) -- Final/terminal F-coalgebra -- -- The full computation tree of an automaton. -- -- In Agda, we have only weakly final coalgebras. -- Obtained as greates fixed-point of F record Colist A : Set where coinductive field force : ListF A (Colist A) open Colist using (force) -- Coiteration is defined via copattern matching. collatz : ℕ → Colist ℕ force (collatz n) with collatzStep n ... | nil = nil ... | cons m n' = cons m (collatz n') -- abstracting out mapF upsets the termination checker. {-# TERMINATING #-} collatz' : ℕ → Colist ℕ force (collatz' n) = mapF collatz' (collatzStep n) -- General coiteration {-# TERMINATING #-} unfold : ∀{A S} (t : S → ListF A S) → S → Colist A force (unfold t s) = mapF (unfold t) (t s)