我正在使用 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 那样跟踪状态?这是向上顺序的 cataM
, State
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/