I have this code to transform some data:
newtype XXX = XXX
{ xxx :: [ Text ]
} deriving (Eq, Show)
oldToNew
:: [XXX] -> [(Int, [(Int, Text)])]
-> [[(Int, Int, Text)]]
oldToNew xs old = map go1 xs
where
go1 (XXX eqs) = foldr go2 [] eqs
go2 l acc = foldr (go3 l) acc old
go3 l (i, w) acc = foldr (go4 i l) acc w
go4 idx1 label1 (idx2, label2) acc =
if label1 == label2
then (idx1, idx2, label2):acc
else acc
Note two things:
How would one use Control.Lens and/or Optics to do the above.
Test case:
oldToNewSpec :: Spec
oldToNewSpec =
it "oldToNew" $
oldToNew [ XXX ["this", "that", "also"]
, XXX ["here", "there"] ]
[ (0, [(4, "this")])
, (0, [(1, "here")])
, (1, [(5, "that")])
, (2, [(2, "also")])
, (2, [(3, "there")]) ]
`shouldBe`
[ [(0,4,"this"),(1,5,"that"),(2,2,"also")]
, [(0,1,"here"),(2,3,"there")] ]
I don't think you need lenses to make this significantly more readable. List comprehensions ought to get you where you need to go without too much trouble.
oldToNew :: [[Text]] -> [(Int, [(Int, Text)]] -> [[(Text, Int, Int)]]
oldToNew tss rs = [[(t, b, e) | t <- ts, (b, te) <- rs, (e, t') <- te, t == t'] | ts <- tss]
Using a proper data structure will make things significantly more efficient, and probably more readable.
oldToNew :: Ord k => Map k v -> [[k]] -> [[(k, v)]]
oldToNew kvs = map (concatMap look) where
look k = case M.lookup k kvs of
Nothing -> []
Just v -> [(k, v)]