Возьмем две функции:
f :: a -> Maybe b
g :: b -> Maybe c
Функция >>=
будет работать таким образом, что f >>= g
выполнит g
с результатом f
, только если это не Nothing
. Другими словами, для достижения любого результата требуется как f
, так и g
.
Я реализую парсер и понял, что мой лексер выиграет от некоторой противоположности этого. То есть:
f :: a -> Maybe b
g :: a -> Maybe b
planb :: (a -> Maybe b) -> (a -> Maybe b) -> (a -> Maybe b)
planb f g = \x -> case f x of
Nothing -> g x
res -> res
что означает try f
, и если он не работает, попробуйте g
в качестве плана резервного копирования. С помощью lexer это означает попытку сопоставить токен с текущим входом, и если он не сработал, попробуйте сопоставить другой тип токена (который в конечном итоге будет привязан для всех типов токенов).
Поиск Hoogle не привел к какой-либо такой функции, но мне такая функция кажется полезной во многих местах!
Мой вопрос, таким образом, существует ли вариант planb
, который я должен использовать? Если нет, делаю ли я что-то необыкновенное, и есть лучший способ добиться того, чего я хочу?
P.S. Я подумал о том, имеет ли смысл такая функция для Monad
вообще, но она не имеет для меня такого смысла вне Maybe
и, возможно, нескольких других.