Haskell Fix上的类mapAccumR递归方案?
我正在使用来自的函数,并努力弄清楚它是否提供了一些通用的Haskell Fix上的类mapAccumR递归方案?,haskell,recursion-schemes,Haskell,Recursion Schemes,我正在使用来自的函数,并努力弄清楚它是否提供了一些通用的mapAccumR。足以实现的功能,例如: f :: [Int] -> (Int,[Int]) f [] = (0,[]) f (x:xs) = let (sz,xs') = f xs in (sz+x, x*sz : xs') …在修复-ed结构的单次传递中,如: data L a as = Empty | C a as input :: Fix (L Int) input = Fix (C 1 (Fix (C 2 (Fix
mapAccumR
。足以实现的功能,例如:
f :: [Int] -> (Int,[Int])
f [] = (0,[])
f (x:xs) = let (sz,xs') = f xs in (sz+x, x*sz : xs')
…在修复
-ed结构的单次传递中,如:
data L a as = Empty | C a as
input :: Fix (L Int)
input = Fix (C 1 (Fix (C 2 (Fix Empty))))
似乎是我想要的,除了我需要访问最终的b
(上面示例中的最终总和)
我的实际用例是在注释时对AST进行类型检查,并返回表达式的类型。您希望通过
Fix f
调整值向上下降,同时像mapAccumR那样跟踪状态吗?这是向上顺序的cataM
,状态的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
都没有经过测试
或者您希望每个分支的状态都是本地的吗?您希望使用哪种类型的签名?另外,您可能应该看看para
。但是回到我的第一个问题,mapAccumR
是可遍历的
函子的一个已知概念;对于任意类型的不动点,它应该意味着什么还不太清楚。所以我认为para
足够强大,可以实现f
,但是在二次时间内,这是我不想要的。我想我也可以做两个cata
,一个是标记和累积大小,另一个是再次从子树中删除这些大小,但我也不想这样做。你是对的,如果我认真考虑签名的话,我可能是回答我自己问题的最佳方式,但我想我已经决定无论如何这都是相当愚蠢的。递归方案
的文档真的很棒。很明显,zygo
是一条路要走。谢谢,我的实际示例是一个AST,我在其中一次检查并注释树。因此,在每个级别上,我们都需要访问子类型并为父类型返回一个类型。不过这里有几点,我很感激你的回答
makeClassyPrisms ''L
f = (`runState` 0) . transformMOf . _Fix . _C . _1 $ \x -> do
sz <- id <<+= x
return $ x*sz