我有一些代码可以递归地近似解决方案,它实际上做什么并不重要,但它通过改变 mg 对 r' == rt 起作用(我猜,从 4.0 开始,因为我“知道”应该在球场上) .

solve_m f ar st qt = solve_m' f ar st qt 4.0
  where
    solve_m' f ar st qt mg
      | rd > precis    = f' (mg - sf)
      | rd < (-precis) = f' (mg + sf)
      | otherwise = mg
        where
          f' = solve_m' f ar st qt
          rt = st + qt
          r' = f st ar mg
          rd = rt - r'
          sf = abs(rd)

我希望能够做的是计算周期数,我知道正确的方法是使用 State monad,但是将 put/get 放入这样的函数的最优雅的方法是什么?制作一个 do 块?或者只是添加一个计数器solve_m'并返回(counter, mg)?

谢谢!

编辑:这似乎基本上是我想要的,不需要 Monads:
solve_m f ar st qt = (last (series), length(series))
  where
  series = takeWhile termPred (iterate solve_m' 4.0)
  termPred m' = (abs (rt - (f st ar m'))) > precis
  rt = st + qt
  solve_m' mg
    | rt > r' = (mg - sf)
    | rt < r' = (mg + sf)
      where
        r' = f st ar mg
        rd = rt - r'
        sf = abs(rd)

看起来仍然有点乱(重复的代码),但我会整理它...这让我可以接受的结果是它将替换的代码迭代的 1/10000!

最佳答案

在不查看您的算法的情况下,执行此操作的通用方法是将您的终止条件与迭代算法分开:

terminationPred :: a -> Bool
algorithm :: a -> a

然后使用 iterate 和 takeWhile:
itermediates = takeWhile (not . terminationPred) . iterate algorithm
resultAndRecursions :: a -> (a, Int)
resultAndRecursions a = (last (intermediates a), length (intermediates a) - 1)
-- you'd want to make your own safe function here, not use last and length

或展开:
intermediates = unfoldr op
  where
  op a | terminationPred a = Nothing
       | otherwise = let a' = algorithm a
                     in Just (a', a')

编辑:还要注意这两个中间体略有不同,因为第一个保持基本情况(输入 a ,因此是 - 1 ),而第二个没有,因此在互补的 resultAndRecursions 中会有细微差别。

关于haskell - 计算递归次数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3926681/

10-11 04:22
查看更多