Packet Stack Overflow.

I am experimenting with another Depth-First Search implementation with scalaz .

This traverse should be handled broad along with deep tree structures.

The main idea is that subordinate elements should be generated in accordance with some “state”. For example, a set of items marked as visible to avoid them in the future.

Here's the simplest implementation I've come up 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 handles deep search.

class RangeSearchState extends DepthFirstState[Int, Int] {
  def build(elem: Int) = get[Int] map (limit ⇒ if (elem < limit) List(elem + 1) else Nil)
}

, , i i+1, limit, . Reader State, .

new RangeSearchState go 1 run 100

.

new RangeSearchState go 1 run 1000

StackOverflowError.

DepthFirstState, StackOverflow ?

+4
1

, traverseSTrampoline, . , , :

import scalaz._, scalaz.std.list._, scalaz.syntax.traverse._

(0 to 10000).toList.traverseU(_ => State.get[Unit]).run(())

( , traverseS traverseSTrampoline State):

(0 to 10000).toList.traverseS(_ => State.get[Unit]).run(())

, - . , :

import scalaz._
import scalaz.std.list._
import scalaz.syntax.traverse._

abstract class DepthFirstState[E, S] {
  type TState[s, a] = StateT[Free.Trampoline, s, a]

  def build(elem: E): TState[S, List[E]]

  def go(start: E): TState[S, List[E]] = for {
    xs <- build(start)
    ys <- xs.traverseU(go)
  } yield start :: ys.flatten
}

class RangeSearchState extends DepthFirstState[Int, Int] {
  def build(elem: Int): TState[Int, List[Int]] =
    MonadState[TState, Int].get.map(limit =>
      if (elem < limit) List(elem + 1) else Nil
    )
}

:

val (state, result) = (new RangeSearchState).go(1).run(10000).run

, State cats:

import cats.state.State
import cats.std.function._, cats.std.list._
import cats.syntax.traverse._

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.traverseU(go)
  } yield start :: ys.flatten
}

class RangeSearchState extends DepthFirstState[Int, Int] {
  def build(elem: Int): State[Int, List[Int]] =
    State.get[Int].map(limit => if (elem < limit) List(elem + 1) else Nil)
}

val (state, result) = (new RangeSearchState).go(1).run(10000).run

.

+12

Source: https://habr.com/ru/post/1616544/


All Articles