Изменить все четные значения с помощью линзы

Предположим, у меня есть такой массив: [1, 2, 3, 4]

Как мне изменить только четные значения, используя пакет линз? Я ищу что-то вроде:

filterLens even (+10) $ [1, 2, 3, 4]
=> [1, 12, 3, 14]

person Vlad the Impala    schedule 06.06.2014    source источник


Ответы (2)


Prelude Control.Lens> [1, 2, 3, 4] & each . filtered even %~ (+ 10)
[1, 12, 3, 14]

Чтобы найти такие функции, вы можете указать hoogle искать пакет линз, введя «+ линзы» в поле поиска. В этом случае: http://www.haskell.org/hoogle/?hoogle=%2Blens+filter

person Toxaris    schedule 07.06.2014

Ну, если мы посмотрим на тип, который мы хотим

evens :: Lens' [a] [a]

Кажется, что это должен быть действующий объектив, если мы не будем колебаться с длиной сфокусированного списка. Таким образом, относительно легко построить с использованием пар геттера и оседлости.

evens = lens get set where
  get (a:b:xs) = b : get xs
  get _ = []

  set [] xs = xs
  set xs [] = xs
  set (x:xs) (y:ys) = x:y:set xs ys

Но если мы обратим пристальное внимание на функцию set, мы увидим трудности с реализацией полной filterLens: мы злоупотребляем тем, что знаем точную структуру цели линзы. Общий filterLens должен иметь возможность реконструировать порядок восстановления общего типа, используя только его часть. Для общих типов и предикатов это невозможно или, по крайней мере, трудно автоматизировать.

person J. Abrahamson    schedule 06.06.2014