使用Lenses用IO数据填充一些复杂结构的正确方法是什么


{- Some code to illustrate what I mean: -}
module Main where
import System.IO
import Control.Monad
import Control.Lens
import Data.UUID
import Data.UUID.V4
-- I have complex data structure (initially, JSON) and I can use
-- Data.Aeson.Lens to work with this structure. It's pretty comfortble
-- in most cases. But let's suppose we have broken data structure.
-- Instead of "a" I need to have unique key. Easiest way is to use GUID.
ds = [ [("a", "z"),("a", "x"),("a", "c")]
, [("a", "v"),("a", "b"),("a", "n")]
, [("a", "m"),("a", ","),("a", ".")]
]
-- So that's how we can get unique ID.
getId :: IO String
getId = toString <$> nextRandom
main :: IO ()
main = do
-- To insert unique ID I can use a awkward way like this:
-- generate pool of ids that is big enough.
let count = length $ ds ^.. traversed <.> traversed
ids <- forM [0..count * count] $ const getId
-- use Indexed Lens to have list of IDs for each data structure level
-- and insert ID from pre generated list where I need it
let ds' = ds & traversed <.> traversed %@~
((i1, i2) v -> v & _1 %~
(v' -> (ids !! (i1 * count + i2)) ++ v'))
print ds'
-- It works. But I wonder if there is some better way to do the same.

是的,有更好的方法。你只是错过了组合子镜头提供的一些功能。我建议traverseOf,尽管它在镜头库中也有其他几个别名。。。所有这些都只是作为id实现的。。。

ds' <- traverseOf (traverse . traverse . _1) (const getId) ds

最新更新