【问题标题】:mapAccumR -like recursion scheme over Fix?在 Fix 上的 mapAccumR 类递归方案?
【发布时间】:2017-05-04 18:40:25
【问题描述】:

我正在使用recursion-schemes 中的函数,并努力弄清楚它是否提供了泛化mapAccumR 的东西。足以实现的功能,例如:

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

...对Fix-ed 结构进行单次传递,例如:

data L a as = Empty | C a as

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

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

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

【问题讨论】:

  • 你希望得到什么样的类型签名?
  • 另外,你应该看看para
  • 但回到我的第一个问题,mapAccumRTraversable 函子的一个已知概念;对于任意类型的固定点,它应该意味着什么还不太清楚。
  • 对,所以我认为para 足够强大,可以实现f,但在二次时间中我不想要。我想我也可以做两个cata,一个用来标记和累积大小,另一个用来再次从子树中删除这些大小,但我也不想这样做。你是对的,如果我认真考虑签名,我可能会回答我自己的问题,但我认为我已经决定这一切都是相当愚蠢的
  • recursion-schemes 的文档非常棒。显而易见,zygo 是要走的路。

标签: haskell recursion-schemes


【解决方案1】:

您想通过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

所有未测试。

或者您希望每个分支都本地化状态?

【讨论】:

  • 谢谢,我的实际示例是一个 AST,我在其中一次对树进行类型检查和注释。因此,在每个级别,我们都需要访问子类型并为父级返回一个类型。不过这里有几点,我很感激你的回答
猜你喜欢
  • 2017-05-22
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-06
  • 2011-07-01
相关资源
最近更新 更多