Составьте линзы с доступом к внешнему типу во время получения и установки
Предположим, у меня есть функция, которая извлекает некоторое внутреннее значение, используя другое внутреннее значение из внешнего значения.
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