【发布时间】:2021-07-18 19:18:29
【问题描述】:
我是 lens 的新手,并尝试使用它对嵌套结构进行许多小的修改,这可能会失败并可能返回其他结果:
element -> Maybe element
element -> Maybe (result, element)
我如何通过索引修改内部结构,如果索引不存在也返回Nothing?如果我使用traverseOf+ix:
type Thing = (String, [Int])
exampleThing :: Thing
exampleThing = ("example", [0, 1])
predMaybe :: Int -> Maybe Int
predMaybe x
| x == 0 = Nothing
| otherwise = Just (pred x)
decrementThingAt :: Int -> Thing -> Maybe Thing
decrementThingAt i = traverseOf (_2 . ix i) predMaybe
> decrementThingAt 1 exampleThing
Just ("example",[0,0])
> decrementThingAt 0 exampleThing
Nothing
如果索引不存在,这会默默地返回未修改的结构:
> decrementThingAt 2 exampleThing
Just ("example",[0,1])
而我也想在这里返回Nothing。如果可能的话,我想在镜头组合“内部”进行。我知道我可以使用 preview / ^? “outside” 来获得 Maybe 根据光学是否匹配任何目标:
> preview (_2 . ix 1) exampleThing
Just 1
> preview (_2 . ix 2) exampleThing
Nothing
但我希望能够写出类似traverseOf (_2 . ix i . <strong>previewed</strong>) predMaybe 的东西。我看到了一些“在外面”做这件事的尴尬方式,比如foldMapOf:
decrementThingAt i = getFirst . foldMapOf (_2 . ix i) (First . predMaybe)
但是有没有办法让所有东西都在同一个管道中,这样我就不会重复/明确地拆卸和重新组装结构?
我也不太明白如何将它与返回额外结果结合起来。目前我正在像这样使用StateT 和zoom:
import Control.Lens (_1, zoom)
import Control.Monad.Trans.State (StateT, runStateT)
import Data.List (uncons)
-- NB: uncons :: [a] -> Maybe (a, [a])
pop :: Thing -> Maybe (Char, Thing)
pop = runStateT $ zoom _1 $ StateT uncons
> pop exampleThing
Just ('e',("xample",[0,1]))
> pop ("", [0, 1])
Nothing
但我仍然不知道如何在缺少索引的情况下使用它,例如,使用 type ThingMaybe = (Maybe String, [Int]) 并且如果 Maybe 是 Nothing 则失败。
【问题讨论】:
标签: haskell haskell-lens lenses