Я пишу библиотеку синтаксического анализатора с использованием комбинаторов Parsec и хочу провести модульное тестирование некоторых моих анализаторов. Итак, у меня есть простой парсер:
dash :: GenParser Char st Char
dash = char '-'
Я бы хотел написать несколько тестов для этого. Положительный тест довольно прост:
spec :: Spec
spec = do
describe "dash" $ do
it "parses a dash" $
parse dash "N/A" "-" `shouldBe` (Right '-')
Я бы тоже хотел написать отрицательный тест. Когда парсер не совпадает, он возвращает Left
из ParseError
. Я хотел бы написать тест, который проверяет точное сообщение, которое содержит ParseError
. Так что я действительно хотел бы сделать что-то вроде
spec :: Spec
spec = do
describe "dash" $ do
it "doesn't parse an underscore" $
parse dash "N/A" "_" `shouldSatisfy` (hasErrorMessage "not a dash")
hasErrorMessage (Left (ParseError _ msgs)) expected = msg == expected
hasErrorMessage _ expected = False
Но у меня возникают проблемы при написании такого рода кода, поскольку конструктор данных ParseError
не экспортируется из Text.Parsec.Error
.
Есть ли способ использовать сопоставление с образцом в типах, где в области действия нет конструктора данных для этого типа?
Я знаю, что мог бы написать hasErrorMessage
что-то вроде
hasErrorMessage :: String -> (Either ParseError a) -> Bool
hasErrorMessage expected (Left pe) = elem expected $ fmap messageString (errorMessages pe)
но я бы тоже хотел понять этот нюанс.