Haskell自定义解析器正确性验证:如何在GHCi中快速测试
验证Haskell自定义解析器的方法
你写的Parser Char Year这类解析器是纯描述性的计算结构,本身不会直接处理字符串输入,必须通过专门的“运行器”函数触发解析流程。以下是几种快速验证的实用方式:
1. 自定义运行器函数(针对手写Parser类型)
如果你的Parser是作业要求手写的递归下降解析器(自定义Monad),通常需要配套实现一个运行函数,比如:
-- 示例运行器:返回成功结果或错误信息 runParser :: Parser a -> String -> Either String a runParser parser input = -- 填充你的解析执行逻辑
在GHCi中直接调用这个函数测试:
> runParser parseYear "2004" Right (Year 2004) > runParser parseYear "abcd" Left "解析失败:输入不是合法4位年份"
2. 用Parsec库自带工具(若使用Parsec实现)
如果作业允许使用Parsec库,它提供了现成的调试工具:
parseTest:直接在GHCi打印解析结果,适合快速调试parse:返回包含位置信息的详细结果
示例用法:
import Text.Parsec parseYear :: Parser Year parseYear = Year <$> (read <$> count 4 digit)
在GHCi中测试:
> parseTest parseYear "2004" Year 2004 > parse parseYear "测试输入" "0023" Right (Year 23) > parse parseYear "测试输入" "23" Left "测试输入" (line 1, column 3): unexpected end of input expecting digit
3. 编写单元测试(批量验证场景)
如果需要系统验证多组用例,可以用HUnit或QuickCheck:
HUnit示例(固定用例验证)
import Test.HUnit testParseYear :: Test testParseYear = TestList [ TestLabel "合法年份2004" $ TestCase $ assertEqual "2004解析失败" (Right (Year 2004)) (runParser parseYear "2004") , TestLabel "非法年份abcd" $ TestCase $ assertBool "abcd未触发错误" (isLeft (runParser parseYear "abcd")) ] -- 在GHCi中运行测试 > runTestTT testParseYear
QuickCheck示例(随机输入验证)
import Test.QuickCheck -- 生成随机合法4位年份字符串 validYearStr :: Gen String validYearStr = replicateM 4 (choose ('0','9')) -- 验证所有合法输入都能正确解析 prop_ValidYearParses :: Property prop_ValidYearParses = forAll validYearStr $ \s -> case runParser parseYear s of Right (Year y) -> show y == s Left _ -> False
在GHCi中运行:
> quickCheck prop_ValidYearParses +++ OK, passed 100 tests.
内容的提问来源于stack exchange,提问作者Jord van Eldik
相关产品推荐
相关产品推荐

