Is there a shorter/cleaner way of writing the following snippet of code:
fromMaybe "" $ fmap (^. fullName) (bi ^. bookerContact)
Here bi ^. bookerContact
may result in a Maybe Contact
record, which is why ^. fullName
needs to be fmapped. After the nested traversal, if we end up with a Nothing
we use fromMaybe ""
to default it to a blank string.
A simple way of tidying it is using maybe
instead of the fromMaybe
/fmap
combo:
maybe "" (^. fullName) (bi ^. bookerContact)
You can also introduce the _Just
prism to express all of the drilling down as a single optic:
fromMaybe "" (bi ^? bookerContact . _Just . fullName)
Note that we have switched from (^.)
to (^?)
. That reflects how adding _Just
to the chain changes what used to be a lens (and reach exactly one target) into a traversal (which might reach no targets).
It is also possible to take advantage of Text
being a monoid and use fold
from Data.Foldable
...
fold (bi ^? bookerContact . _Just . fullName)
... or foldOf
, if you prefer the lens spelling:
foldOf (bookerContact . _Just . fullName) bi
As the docs point out, foldOf
is equivalent to (^.)
(which is essentially view
specialised to (->)
), so this will also work, by folding the Maybe Text
:
bi ^. bookerContact . _Just . fullName