Search code examples
haskellhaskell-lens

Compose lenses with accessing outer type during getter and setter


Suppose I have a function which extracts some inner value using other inner value from an outer value

func :: outer -> inner1 -> inner2

Then I have a function which cretes a lens between outer value and some other value using this inner2 value

existingLensFunc :: inner2 -> Lens' outer result

Is there a way to create another function which creates a lens betwee outer value and result value using inner1 value?

finalLens :: inner1 -> Lens' outer result

In other words, is there a better way to write this?

finalLens inner1 = lens getter setter
  where setter outer result = let inner2 = func outer inner1 in set (existingLens inner2) result outer
        getter outer = let inner2 = func outer inner1 in view (existingLens inner2) outer

Solution

  • Let's unshorten the types...

    existingLensFunc
       :: Inner2 -> (∀ f . Functor f => (Result -> f Result) -> Outer -> f Outer)
       ≡  ∀ f . Functor f => Inner2 -> (Result -> f Result) -> Outer -> f Outer
    
    finalLens
       :: ∀ f . Functor f => Inner1 -> (Result -> f Result) -> Outer -> f Outer
    

    There's an evident place to “grab off” an Outer here: from the last argument.

    finalLens inner1 fres outer = existingLensFunc (func outer inner1) fres outer