I'm experimenting with different implementation of Depth-First Search with scalaz.
This traverse should handle wide along with deep tree-like structures.
Main idea - subordinate elements should be generated according to some "state". For example set of marked as seen elements to avoid them in future.
Here the simplest implementation I've come with
import scalaz._
import scalaz.syntax.monad._
import scalaz.State._
abstract class DepthFirstState[E, S] {
def build(elem: E): State[S, List[E]]
def go(start: E): State[S, List[E]] = for {
xs ← build(start)
ys ← xs.traverseSTrampoline(go)
} yield start :: ys.flatten
}
We can create the simplest algorithm to test how it handle deep search
class RangeSearchState extends DepthFirstState[Int, Int] {
def build(elem: Int) = get[Int] map (limit ⇒ if (elem < limit) List(elem + 1) else Nil)
}
It's just a tree degraded to linked list, where each element i
has single child i+1
until it reaches limit
encoded in state. While state is not changing it's more Reader
than State
but it's not the case.
Now
new RangeSearchState go 1 run 100
Successfully builds traversed number list. While
new RangeSearchState go 1 run 1000
Falling with StackOverflowError
.
Is there way to fix implementation of DepthFirstState
so it could run without StackOverflow
even on very deep recursion?