\begin{code}
{-# OPTIONS --safe --termination-depth=2 #-}
open import Prelude
module TopoSort {A : Type a} (disc : Discrete A) where
open import Data.Set.Noetherian disc
open import Data.Set.Discrete disc
open import Data.Set
open import Data.RoseTree
GraphOf : Type a → Type a
GraphOf A = A → List A
\end{code}
%<*trace-ty>
\begin{code}
trace : GraphOf A → List A → Forest A
\end{code}
%</trace-ty>
\begin{code}
trace g dom = expand dom ∅ (noeth Dom)
where
Dom : 𝒦 A
Dom = 𝒦-fromList dom
expand : List A → ∀ seen → NoethAcc Dom seen → List (Tree A)
expand [] seen na = []
expand (v ∷ vs) seen (nacc wf) with v ∈? Dom | v ∈? seen
... | yes v∈Dom | no v∉seen =
(v & expand (g v) (v ∷ seen) (wf v v∈Dom v∉seen)) ∷ expand vs seen (nacc wf)
... | _ | _ = expand vs seen (nacc wf)
\end{code}
%<*topo-sort>
\begin{code}
topo-sort : GraphOf A
→ List A → List A
topo-sort g = fst ∘ sort-f ([] , ∅) ∘ trace g
where mutual
sort-f : List A × 𝒦 A → Forest A →
List A × 𝒦 A
sort-f ac [] = ac
sort-f ac (n ∷ ns) = sort-t n (sort-f ac ns)
sort-t : Tree A → List A × 𝒦 A
→ List A × 𝒦 A
sort-t (v & cs) (sorted , seen) =
if does (v ∈? seen)
then (sorted , seen)
else map₁ (v ∷_)
(sort-f (sorted , v ∷ seen) cs)
\end{code}
%</topo-sort>