我正在使用 recursion-schemes 的函数,并努力弄清楚它是否提供了概括 mapAccumR 的东西。一些强大到可以实现的东西,例如:

f :: [Int] -> (Int,[Int])
f [] = (0,[])
f (x:xs) = let (sz,xs') = f xs in (sz+x, x*sz : xs')

...在 Fix 结构的单次传递中,例如:
data L a as = Empty | C a as

input :: Fix (L Int)
input = Fix (C 1 (Fix (C 2 (Fix Empty))))

zygo 似乎几乎是我想要的,除了我需要访问最终的 b(上例中的最终总和)。

我的实际用例是在注释时对 AST 进行类型检查,并返回表达式的类型。

最佳答案

您想通过 Fix f 调整值向上下降,同时像 mapAccumR 那样跟踪状态?这是向上顺序的 cataMState monad 用于跟踪状态。在你的例子中:

f :: Fix (L Int) -> (Fix (L Int), Int)
f = (`runState` 0) $ cataM $ ((.) . fmap) Fix $ \case
  Empty -> pure Empty
  C x xs -> do
    sz <- get
    put $ sz+x
    return $ C (x*sz) xs

使用 lens :
makeClassyPrisms ''L

f = (`runState` 0) . transformMOf . _Fix . _C . _1 $ \x -> do
  sz <- id <<+= x
  return $ x*sz

都未经测试。

或者您希望状态是每个分支的本地状态?

关于haskell - 修复上的类似 mapAccumR 的递归方案?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41227219/

10-12 03:30