Home > Blockchain >  Is there a standard combinator packing the result of a lens in functor?
Is there a standard combinator packing the result of a lens in functor?

Time:12-30

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
  • Related