Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
按值修改Haskell嵌套记录_Haskell_Records_Template Haskell_Lenses - Fatal编程技术网

按值修改Haskell嵌套记录

按值修改Haskell嵌套记录,haskell,records,template-haskell,lenses,Haskell,Records,Template Haskell,Lenses,假设我有一个嵌套结构,如下所示: data Bar = Bar { _id :: Integer, _bars :: [Bar] } data Foo = Foo { _bars :: [Bar] } 我有一个Foo和一堆条以及各种ids: foo = Foo [Bar 1 [Bar 2], Bar 3 [Bar 4, Bar 5]] 我如何使用镜头修改foo,使Bar 5变成Bar 6 我知道我使用fclabels来做这样的事情: mkLabel ''Foo mkLabel ''Bar m

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

data Bar = Bar { _id :: Integer, _bars :: [Bar] }
data Foo = Foo { _bars :: [Bar] }
我有一个
Foo
和一堆
以及各种
id
s:

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

但条可以无限嵌套。如何使用指定的ID定位和修改

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

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens    

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

makeLenses ''Bar

instance Plated Bar where
    plate = bars.traverse
fiveToSix :: Bar -> Bar
fiveToSix = transform go
    where go bar
            | bar^.lbl == 5 = bar & lbl .~ 6
            | otherwise = bar
(如果您不想自己实现
plate
,可以派生
实例并将其保留为空。)

接受修改单个节点并将其应用于整个结构的函数

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens    

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

makeLenses ''Bar

instance Plated Bar where
    plate = bars.traverse
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,让我们使用将所有
条5
条中拉出

fives :: Bar -> [Bar]
fives = toListOf $ cosmos.filtered (views lbl (== 5))

您想根据标签的值或此树中的位置来更新它吗?如果有多个
Bar 5
,您预计会发生什么?似乎
transformOn
transformOnOf
将允许直接处理
Foo
值。@danidiaz Yep,
transformOn
基本上只是在给定镜头内运行
transform
transformOn sg=over s(transform g)