Заставить монаду преуспеть с провалом в haskell - PullRequest
0 голосов
/ 06 марта 2019

У меня есть монада парсера, которая выглядит следующим образом:

data Parser b a = P(b -> [(a, b)])
instance Monad (Parser p) where
  p >>= f = P $ \inp -> case parse p inp of
                           [] -> []
                           [(v, inp')] -> parse (f v) inp'

У меня также есть следующие функции / парсеры для получения и установки состояния парсера:

getState :: Parser b b
getState = P(\inp -> [(inp, inp)])

setState b -> Parser b ()
setState s = P(\inp -> [(), s)]

ДополнительноУ меня есть функция Parser, которая смотрит вперед, чтобы увидеть, есть ли еще что-то для анализа, не потребляя ничего:

lookahead :: Parser b a -> Parser b ()
lookahead p = do
                state <- getState
                result <- p
                setState state
                return result

Теперь, предположим, я хочу написать функцию Parser, которая успешно работает, если другой синтаксический анализатор не удается : он должен потерпеть неудачу, если есть больше, чтобы потреблять и преуспеть, если нет.

notFollowedBy :: Parser b a -> Parser b ()
notFollowedBy p = do --statements

Предполагаемое использование состоит в том, чтобы запретить незаконным парсерам продолжать, согласно некоторой грамматике.

Это поставило меня в тупик: к моему (ограниченному) пониманию монад, они предоставляют вамс защитной сеткой на случай, если любая из оценок не удалась.Есть ли (хороший и рекомендуемый) способ заставить эту функцию делать обратное?

1 Ответ

2 голосов
/ 07 марта 2019

Вот как вы можете реализовать notFollowedBy в вашем парсере:

notFollowedBy :: Parser b a -> Parser b ()
notFollowedBy p = P (\inp -> case parse p inp of
                                [] -> [((), inp)]
                                _  -> [])

Это определение основано на возможности доступа к внутренним элементам Parser (в частности, конструктору P).

В качестве альтернативы вы можете сделать следующее:

notFollowedBy p = do
    inp <- getState
    case parse p inp of
        [] -> return ()
        _  -> fail "sub-parse succeeded"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...