{ Compute new state of DFS from current state }
f::[[Int]] > [[Int]]
f state = y
where
{ no root vertex: empty state returned }
y = if (length(head(state)) == 0) then
[]
{ root depends list empty:
remove root from vertex stack }
else if (lv == []) then
[(tail (head(state))) ] ++
(drop 1 state)
{ root depends list has single vertex:
add root to solution list,
make depends list empty,
remove root from vertex stack }
else if (length(lv) == 1) then
[(tail (head(state))) ] ++
(drop 1 (take (length(z)1) z)) ++
[ v:last(state) ]
{ root depends list lv has > 1 vertex:
head of lv is new root vertex,
head of lv removed from lv }
else
[(take 1 (head (drop (v+1) state))) ++
(head state) ] ++
(drop 1 z)
where
{ root vertex }
v = head(head(state))
{ root's dependency list lv }
lv = (head (drop (v+1) state))
{ remove 1st vertex in lv }
r = (drop 1 lv)
{ put 1st of lv on the vertex stack
replace lv with r }
z = (take (v+1) state) ++
[r] ++
(drop (v+2) state)
{ Perform a DFS until vertex stack is empty }
h::[[Int]] > [[Int]]
h state =
if (head(state) == []) then state
else h(f(state))
{ Set initial root vertex }
setInit::[[Int]] > Int > [[Int]]
setInit state i = [[i]] ++ (drop 1 state)
{ Perform the topological sort }
topo::[[Int]] > [Int]
topo inp = last(last y)
where
state = [[]] ++ inp ++ [[]]
y = [state] ++
[ h(setInit x i)
 x < y
 i < [0..(length(state)3)] ]
{ small example }
ex = [[2,3,4,0],[1],[1,2],[1,5,3],[3,5,4],
[2,5],[1,7,6],[0,2,7]]::[[Int]]

This example illustrates how to manage state changes during execution
of a program. Imperative languages like C++ manage state changes
through assignment statements. Haskell does not have assignment
statements. A reasonable solution to the problem of managing
changing state is to create a tail recursive function that computes
the new state and passes the new state as an argument to the next
recursive call of the function where the next state is computed.
This is done here in developing a program that computes a topological
sort of a partial order. A few definitions are presented and then a
description of the code.
A partial order is a relation R on a collection of vertices
such that there is no cycle. For example, v1 R v2, v2 R
v3, ... vn R v1 is a cycle. If v1 R v2 then
v1 is said to directly depend on v2.
A total order is a list [v1,v2,v3...] of vertices such
that, for any i < j, vj R vi is false.
A state contains three parts
A stack of vertices, the leftmost of which is called the
root vertex. A total order is found for a given partial order, in whole
or in part, via a depthfirst search beginning at some root vertex.
A list of lists, one for each vertex, in order of vertex
index. Each list contains the dependencies of the associated
vertex and ends with the vertex number itself.
A solution vector, initially empty. This will contain a
total order of all vertices in the given partial order.
See the small example ex to the left for an example of state:
the root vertex is 0, vertices are numbers 07 and their dependency
lists are given by the middle 8 lists in the state, the last list is
the solution list which is empty. When the topological sort is finished
the state looks like this:
[[],[],[],[],[],[],[],[],[],[6,7,0,4,3,5,2,1]]
Function f makes one step of the depthfirst search and
returns the corresponding new state given some previous state.
The input to f is a state. The output of f is
a state derived from the input state in one of four ways.
If there is no root vertex, the empty state is returned
If there is a root vertex v but the dependency list associated
with v is empty, then v is removed from the vertex stack.
If there is a root vertex v and the dependency list associated
with v contains one vertex number, then v is placed at
the head of the solution list, the dependency list becomes empty, and
v is removed from the vertex stack. Execution of this step means
that all dependencies of v have been added to the solution list
and search has backed up to v so it is safe to add v
to the solution.
If there is a root vertex v and the dependency list
Lv associated with v contains more than one vertex,
then the head of Lv becomes the root vertex and is placed on
the vertex stack and that element is removed from Lv.
The following are some sample values to variables in f:
state = [[0,2],[1,2,3],[4,5,6],...,[10,11]]
vertex stack = [0,2]
dependencies = [[1,2,3],[4,5,6],...]
solution list = [10,11]
v is 0 (the root vertex)
lv is [1,2,3] (dependency list for v)
r is [2,3] (remove first vertex of lv from lv)
z is [[1,0,2],[2,3],[4,5,6],...,[10,11]]
(put first of lv on stack, replace lv with r)
Function h makes a depthfirst search for dependencies given
a particular root vertex. Input to function h is a state.
The output of h is a state with the last list giving a
topological ordering of all vertices that root vertex v depends
on plus v and such that the presence of all vertices in the
solution list is removed from the state dependency lists, provided a
root vertex v exists. If there is no root vertex, the input
state is returned without change.
Function setInit sets an initial root vertex in a state that
is presumed to have an empty vertex stack.
The input to setInit is a state and a vertex number v.
The output is exactly the same state as the input except that the
vertex stack consists solely of v.
Function topo performs a topological sort on a partial order.
The input to topo is a list of dependency lists (a partial
order). A state is creating by preceding and appending the input
with [[]], the initial empty vertex stack and empty solution
vector. The output is a total order of vertices from right to left.
The method used is to apply function h to all root vertices
0,1,...n. The output of each call to h is a state that has a
topological sort of vertices up to the current one, plus their
dependencies. That state is input to the next call to h
along with the next higher root vertex number.