While trying to apply a function with multiple layers of functors to a member of a host data structure, as in the following example:
update ::
(SomeProductField -> Maybe (Int, SomeProductField)) ->
(SomeProduct -> Maybe (Int, SomeProduct))
I came up with the following utility:
inFunctor :: Functor f => Lens s t a b -> Lens s (f t) a (f b)
inFunctor lens f = getCompose . lens (Compose . f)
Allowing me to implement the update
function like this:
someProductFieldLens :: Lens' SomeProduct SomeProductField
update = inFunctor someProductFieldLens
I am wondering whether something like this is already present in "lens" and whether the same is achievable somehow otherwise using the existing means.
CodePudding user response:
Not much of a standard approach, perhaps, but anyway: alaf
can handle the Compose
wrapping. For instance:
data SomeProduct = SomeProduct
{ _someProductField :: Bool
, _anotherProductField :: String
}
deriving Show
makeLenses ''SomeProduct
ghci> alaf Compose someProductField (\b -> Just (fromEnum b, not b)) (SomeProduct False "foo")
Just (0,SomeProduct {_someProductField = True, _anotherProductField = "foo"})
If you'd still like to define the general combinator:
inFunctor :: Functor f => Lens s t a b -> Lens s (f t) a (f b)
inFunctor l = alaf Compose l