Самое простое решение, очень похоже на то, что предлагает Бергей , написав обертку вокруг myFun
, чтобы она могла обрабатывать Node
с, а не Element
с:
myFun' :: Node -> [Node]
myFun' n = case n of
NodeElement el -> myFun el
_ -> [n]
myFun'
может затем использоваться с простым concatMap
(в отличие от concatMapOf
) для изменения поля nodes
:
over nodes (concatMap myFun')
Как оказалось, есть кусок объектива магии, который можно использовать как альтернативный способ написания обертки. Комбинатор outside
превращает призму в линзу, нацеленную на функцию, что позволяет нам, по сути, редактировать, что функция делает в конкретном случае. На практике это выглядит так:
over nodes (concatMap $ set (outside _Element) myFun (:[]))
Аргумент concatMap
- это функция, которая ведет себя подобно (:[])
, за исключением случаев, когда аргумент соответствует _Element
, и в этом случае он становится myFun
в базовом элементе. То есть, по сути, абстрактное сопоставление с образцом. Чтобы понять суть дела, мы можем попробовать имитировать стиль определения myFun'
выше, используя outside
:
myFun' :: Node -> [Node]
myFun'
= outside _Element .~ myFun
$ \n -> [n]