我正在尝试在Haskell中编写一个简单的迭代算法,但我很难在优雅和速度方面找到最佳解决方案。
我有一个算法需要在多次迭代中对一个状态应用一个操作,直到达到一些停止条件,使用一些任意函数记录状态。我已经知道如何通过定义像iterateM这样的函数来实现这样的方案。
但是在这种情况下,为每个步骤执行的操作取决于状态,并归结为检查“步骤类型”条件以决定下一个迭代类型,然后执行后续10次迭代的操作A,或者在再次检查条件之前执行下一次迭代的操作B.
我可以用命令式的方式写出:
c=0
while True:
if c>0:
x=iterateByA(x)
c=c-1
else:
if stepCondition(x)==0:
x=iterateByA(x)
c=9
else:
x=iterateByB(x)
observeState(x)
if stopCondition(x):
break
当然这可以在Haskell中复制,但我宁愿做一些更优雅的事情。
我的想法是让迭代使用一个函数列表来弹出并应用于状态,并在它为空时用新的列表(基于“步骤类型”条件)更新该列表。我有点担心这会效率低下。会这样做并使用像
这样的东西take 10 (repeat iterateByA)
将所有列表分配等编译成仅使用计数器的紧密循环,就像上面的命令一样?
还有另一种干净利落的方法吗?
如果这对于自适应随机模拟算法有帮助,则迭代步骤更新状态,步骤条件(决定最佳模拟方案)是当前状态的函数。实际上有3种不同的迭代方案,但我认为2的例子更容易解释。
(我不确定它是否重要,但我也应该指出,在haskell中,iterateByX函数是monadic,因为它们使用随机数。)
答案 0 :(得分:1)
直接翻译看起来并不太糟糕。
loop c x
| stopCondition x = observe x
| c > 0 = observe x >> iterateByA x >>= loop (c-1)
| stepCondition x = observe x >> iterateByA x >>= loop 9
| otherwise = observe x >> iterateByB x >>= loop c
observe
的重复可以通过各种技巧删除,如果你不喜欢它。
但你可能应该重新思考一些事情。这是一种非常迫切的方法;可能会做得更好(但很难说你在这里给出的一些细节如何)。