Optics and lenses are, in my opinion, one of PureScript’s killer features.
I remember @monoidmusician teaching me how to use them to deal with a horrible set of deeply-nested maps I’d set up and having one of those functional programming aha! moments. Since then I’ve found them used pervasively through production code at companies I’ve worked for, but not very much written about how to use them to solve practical problems in PureScript.
If you haven’t used optics before, or if you’re still not as comfortable with them as you’d like, this article will help you become more adept using them to solve real problems in your code.
If you learned something new, please consider sharing this with your colleagues, Twitter followers, or other folks who might find it interesting and useful, too.
@thomashoneyman I finally managed to go through this, and it’s such a lovely introduction to lenses and prisms and now I’m recommending it to friends and family
So thanks a lot for writing your posts (I also loved the React one) as you do, it’s easy to see you put great care in making things clear and understandable and with a nice learning curve
An excellent article! I like your discussion of the conventions your prefer to use with traversals when they are affine or not. I wish the conventional names of everything in optics encoded the intended uses rather than sounding generic.
BTW, I think there’s a typo where ix should be index:
Given an index, creates a traversal for a structure s , indexed by type ix and focusing on type a .
type NestedData =
Maybe (Array { foo :: Tuple String (Either Int Boolean), bar :: String })
Where
_NestedInt :: Int -> Traversal' NestedData Int
_NestedInt index = _Just <<< ix index <<< _foo <<< _2 <<< _Left
getNestedInt :: Int -> NestedData -> Maybe Int
getNestedInt index = preview (_NestedInt index)
What would be the index used to get the Int? 0?
I am visualising the walk back process like walking back a tree from the leaves, if that makes sense?
The index refers to the array, and _NestedInt leaves the specific index up to you – if you wanted to get the Int out of the first record in the array you’d do:
_FirstNestedInt :: Traversal' NestedData Int
_FirstNestedInt = _NestedInt 0