gpt4 book ai didi

haskell - 按值修改 Haskell 嵌套记录

转载 作者:行者123 更新时间:2023-12-05 00:52:32 26 4
gpt4 key购买 nike

假设我有一个嵌套结构如下:

data Bar = Bar { _id :: Integer, _bars :: [Bar] }
data Foo = Foo { _bars :: [Bar] }

我有一个 Foo有一堆 Bars与各种 id年代:
foo = Foo [Bar 1 [Bar 2], Bar 3 [Bar 4, Bar 5]]

怎么样,也许是用镜头,我修改 foo这样 Bar 5变成 Bar 6 ?

我知道我使用 fclabels做这样的事情:
mkLabel ''Foo
mkLabel ''Bar
modify bars (\bars -> ...) foo

但是条形可以无限嵌套。如何定位和修改 Bar有指定的ID?

最佳答案

是的,lens可以做到这一点。 Control.Lens.Plated 模块包含用于“废弃您的样板”式编程的工具,具有自相似结构,如您的 Bar .这个想法非常简单:你解释了如何找到一个节点的直接子节点(通过编写 Traversal' a a ),然后库递归地将该遍历应用于整个结构。

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data Bar = Bar { _lbl :: Int, _bars :: [Bar] } deriving (Show)

makeLenses ''Bar

instance Plated Bar where
plate = bars.traverse

(如果您不想自己实现 plate,可以推导出 Data 并将 instance 留空。)

transform :: Plated a => (a -> a) -> a -> a 接受一个修改单个节点并将其应用于整个结构的函数。
fiveToSix :: Bar -> Bar
fiveToSix = transform go
where go bar
| bar^.lbl == 5 = bar & lbl .~ 6
| otherwise = bar

使用您问题中的示例:
ghci> let bars = [Bar 1 [Bar 2 []], Bar 3 [Bar 4 [], Bar 5 []]]
ghci> map fiveToSix bars
[Bar 1 [Bar 2 []], Bar 3 [Bar 4 [], Bar 6 []]]

再举一个例子,对于 funzies,让我们使用 cosmos 拉所有 Bar 5来自 Bar .
fives :: Bar -> [Bar]
fives = toListOf $ cosmos.filtered (views lbl (== 5))

关于haskell - 按值修改 Haskell 嵌套记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42516064/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com