Haskell自定义Parser类型检查子串报错:模式匹配解析错误排查
问题分析与解决
你的代码存在几个关键问题,导致语法和逻辑错误:
1. Case语句的语法错误
Haskell的case表达式分支是模式匹配,不能直接写条件判断表达式(比如(isInfixOf "true", s) == True)。正确的做法是使用guard(|)或直接用条件表达式处理逻辑。
2. 类型不匹配问题
你导入了Data.Text的函数,但Parser的输入是String类型,而Data.Text.isInfixOf和replace的参数是Text类型,直接混用会导致类型错误。如果要使用String,应该用Data.List中的字符串操作函数。
3. 逻辑不符合需求
你的需求是:只有当字符串以"true"或"false"开头时才匹配(比如"ttruehello"包含"true"但不是前缀,所以返回Nothing),但你用了isInfixOf(检查任意子串存在),这和需求矛盾。同时,匹配到"false"时应该返回False,而不是True。
修正后的代码
import Data.List (isPrefixOf) newtype Parser a = Parser (String -> Maybe (String, a)) parseBool :: Parser Bool parseBool = Parser (\s -> if "true" `isPrefixOf` s then Just (drop 4 s, True) else if "false" `isPrefixOf` s then Just (drop 5 s, False) else Nothing)
代码解释
- 使用
Data.List.isPrefixOf检查字符串是否以目标前缀开头,完全符合需求中的匹配规则。 - 用
drop函数去掉匹配的前缀部分:"true"长度为4,所以drop 4;"false"长度为5,所以drop 5。 - 逻辑清晰:先检查"true"前缀,再检查"false"前缀,都不匹配则返回
Nothing。 - 避免了类型不匹配问题,直接使用
String类型的操作函数。
测试验证
- 输入
"truehello":返回Just ("hello", True),符合需求。 - 输入
"ttruehello":因为不是以"true"开头,返回Nothing,符合需求。 - 输入
"falseworld":返回Just ("world", False),正确处理false分支。
内容的提问来源于stack exchange,提问作者Mon
相关产品推荐
相关产品推荐

