Skip to content

Instantly share code, notes, and snippets.

@ChrisPenner
Created September 14, 2019 18:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChrisPenner/f58df3d85a0d01b55ae17c8eb961b4a3 to your computer and use it in GitHub Desktop.
Save ChrisPenner/f58df3d85a0d01b55ae17c8eb961b4a3 to your computer and use it in GitHub Desktop.
Gain extra context in your lens chain by passing values as an index!
Sometimes when diving deep with optics you need to reference something earlier in your path after you dive deeper. Just stash it in your index!
Let's say we want to know which pets belong to which owner, we've got the data paired up like this:
pets :: [(String, [String])]
pets =
[ ("Steven", ["Spot", "Mittens"])
, ("Kaylee", ["Pepper", "Sparky"])
]
We can traverse the top level, stashing away the owner's name. Each index remains paired with its own set of child branches.
>>> pets ^@.. -- Starting with all pets, we want an INDEXED (@) list of focuses
folded -- Fold over the top-list, focusing each (owner, pets) tuple
. reindexed fst selfIndex -- Take the focus as our index, but then apply `fst` to it
<. _2 -- <. says to use the earlier index for the next part, then dive into _2
. folded -- fold over the list of pet names, focusing each one
Altogether now:
>>> pets ^@.. folded . reindexed fst selfIndex <. _2 . folded
[ ("Steven", "Spot")
, ("Steven", "Mittens")
, ("Kaylee", "Pepper")
, ("Kaylee", "Sparky")
]
`@` always means "with an index", and for `itoListOf` a.k.a. `^@..` it pairs results up in a tuple!
This is a contrived use-case, but this comes in extra handy when diving through JSON objects like K8s configs where you need to know which 'thing' you're working on when you're deep inside.
Maybe define a helper for it:
chooseIndex :: (s -> i) -> IndexedLensLike i f s t s t
chooseIndex getIndex = reindexed getIndex selfIndex
Bonus:
In this particular case we can actually just sequence each tuple to distribute the tuple through the list!
>>> pets ^. folded . to sequence
[("Steven","Spot"),("Steven","Mittens"),("Kaylee","Pepper"),("Kaylee","Sparky")]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment