Составьте линзы с доступом к внешнему типу во время получения и установки

Предположим, у меня есть функция, которая извлекает некоторое внутреннее значение, используя другое внутреннее значение из внешнего значения.

func :: outer -> inner1 -> inner2

Тогда у меня есть функция, которая создает линзу между внешним значением и некоторым другим значением, используя это значение inner2

existingLensFunc :: inner2 -> Lens' outer result

Есть ли способ создать другую функцию, которая создает линзу между внешним значением и значением результата, используя значение inner1?

finalLens :: inner1 -> Lens' outer result

Другими словами, есть ли лучший способ написать это?

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

1 ответ

Решение

Давайте отрежем типы...

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

Есть очевидное место, чтобы "схватить" Outer здесь: из последнего аргумента.

finalLens inner1 fres outer = existingLensFunc (func outer inner1) fres outer
Другие вопросы по тегам