Scala 使用状态单子进行重构
下面是纯函数DFS例程,它必须沿Scala 使用状态单子进行重构,scala,Scala,下面是纯函数DFS例程,它必须沿Vector[Boolean]拖动才能进行常量时间查找。有没有一种方法可以使用Statemonad使它更简洁易懂?对于这样一个具体的问题,我很抱歉,我已经读了很多关于这个单子的帖子,其中有Haskell和Scala中的例子,但仍然不明白 object Digraph { def apply(n: Int) = new Digraph(n, Vector.fill(n)(List.empty[Int])) } class Digraph private (va
Vector[Boolean]
拖动才能进行常量时间查找。有没有一种方法可以使用State
monad使它更简洁易懂?对于这样一个具体的问题,我很抱歉,我已经读了很多关于这个单子的帖子,其中有Haskell和Scala中的例子,但仍然不明白
object Digraph {
def apply(n: Int) = new Digraph(n, Vector.fill(n)(List.empty[Int]))
}
class Digraph private (val n: Int, val adj: Vector[List[Int]]) {
def addEdge(u: Int, v: Int) = new Digraph(n, adj.updated(u, v :: adj(u)))
def postOrder(s: Int) = {
def _postOrder(s: Int, ordered: List[Int], visited: Vector[Boolean]): (List[Int], Vector[Boolean]) = {
val newVisited = visited.updated(s, true)
val toVisit = adj(s).filter(!newVisited(_))
val init = (ordered, newVisited)
val reachable = toVisit.foldLeft(init){(acc, v) => _postOrder(v, acc._1, acc._2)}
(s::reachable._1, reachable._2)
}
_postOrder(s, List[Int](), Vector.fill(n)(false))
}
}
这(我认为)是一个等价的实现,使用scalaz.State
:
class Digraph private (val n: Int, val adj: Vector[List[Int]]) {
def addEdge(u: Int, v: Int) = new Digraph(n, adj.updated(u, v :: adj(u)))
def postOrder(s: Int): (List[Int], Vector[Boolean]) = {
type S[A] = State[Vector[Boolean], A]
def _postOrder(s: Int, ordered: List[Int]): S[List[Int]] =
for {
visited <- init[Vector[Boolean]]
newVisited = visited.updated(s, true)
toVisit = adj(s).filterNot(newVisited)
_ <- put(newVisited)
reachable <- toVisit.foldLeftM(ordered){(acc, v) => _postOrder(v, acc)}
}
yield s::reachable
val (a, b) = _postOrder(s, List[Int]()).run(Vector.fill(n)(false))}
(b, a)
}
}
类有向图私有(val n:Int,val adj:Vector[List[Int]]{
def addEdge(u:Int,v:Int)=新的有向图(n,调整更新(u,v::调整(u)))
def后序(s:Int):(列表[Int],向量[Boolean])={
类型S[A]=状态[Vector[Boolean],A]
def_后序(s:Int,ordered:List[Int]):s[List[Int]]=
为了{
访问向量[Boolean]效率低下,因为它会导致每个布尔值的装箱。