You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:20:36