Примените два фолда или геттера и преуспейте только в том случае, если оба успешны

Представьте, что у меня есть следующий список:

lst :: [(Bool, Maybe Integer)]
lst = [(True, Just 3), (True, Nothing), (False, Just 12)]

Используя библиотеку линз, я хочу извлечь элементы кортежей, но я хочу, чтобы это удалось только тогда, когда вторым элементом является Just. Мне нужна оптика split, которая работает следующим образом:

> lst ^.. folded.split (_1.to not) (_2._Just)
[(False, 3), (True, 12)]

Я могу реализовать split сам так:

split :: Getting (First a) s a -> Getting (First b) s b -> Fold s (a, b)
split a b = folding (\x -> (,) <$> (x ^? a) <*> (x ^? b))

… кажется, работает. Тем не менее, это похоже на то, что я должен изобретать велосипед. Есть ли что-то уже предоставленное библиотекой объективов, что делает это таким же хорошим способом?


person Alexis King    schedule 26.07.2017    source источник


Ответы (1)


Комбинатор aside принимает Prism, который работает со вторым компонентом кортежа, и возвращает Prism, который работает со всем кортежем:

ghci> lst ^.. folded.aside _Just
[(True,3),(False,12)]

Полученная призма соответствует, когда компонент соответствует, в противном случае она не работает.

Сочетая его с to и bimap, мы можем воспроизвести ваш пример:

ghci> lst ^.. folded.aside _Just.to (bimap not id)
[(False,3),(True,12)]

Для работы над первым компонентом мы можем использовать swapped:

ghci> [(Just 3,False)]^..folded.swapped.aside _Just.swapped
[(3,False)]
person danidiaz    schedule 26.07.2017