【发布时间】:2014-03-28 18:18:08
【问题描述】:
所以我想写一个图广度优先搜索。该算法跟踪其状态中的一些值。它们是:每个节点的visited 状态和一个队列。
它还需要知道图的边缘以及它的目标是什么,但这不会逐步改变。
这是我想出的(对不起,丑陋)
import Prelude hiding (take, cons, drop)
import Data.Vector
type BFSState = (Vector Bool, Vector [Int], [Int], Int)
bfsStep :: BFSState -> BFSState
bfsStep (nodes, edges, current:queue, target)
| current == target = (nodes, edges, [], target)
| nodes ! current = (nodes, edges, queue, target)
| otherwise = (markedVisited, edges, queue Prelude.++ (edges ! current), target)
where
markedVisited = (take current nodes) Data.Vector.++ (cons True (drop (current + 1) nodes))
bfsSteps :: BFSState -> [BFSState]
bfsSteps init = steps
where steps = init : Prelude.map bfsStep steps
bfsStep 接受一个状态并产生下一个状态。当状态的队列为[]时,目标节点已经找到。 bfsSteps 只是使用一个自引用列表来制作 BFSStates 的列表。现在,目前没有办法知道到达某个节点需要多少步(给定起始条件),但bfsSteps 函数会产生算法所用的步数。
我担心的是每一步都会复制状态。我意识到与 ++ 的连接效果不佳,但我觉得老实说这并不重要,因为每一步都会复制所有状态。
我知道有些 monad 几乎应该做我在这里所做的事情,但是由于 Haskell 是纯的,这是否意味着 monad 仍然必须复制状态?
难道不应该有办法说“嘿,我在我的代码中只使用了一次这些值,而且我没有将它们存储在任何地方。您可以更改它们而不是创建新值”?
如果 Haskell 自己这样做,它仍然可以让我保持代码纯净,但可以加快执行速度。
【问题讨论】: