模式匹配与相等性比较

4
parserChar :: Char -> Parser Char
parserChar c = Parser ch where
   ch d = case dvChar d of
      Parsed c dp -> Parsed c dp
      _ -> NoParse

上面的函数应该接受一个字符 c 并返回一个仅能匹配 c 的解析器。 函数 dvChar d 将返回 Parsed char dpNoParse(其中 char 是字符串中的下一个字符)。 因此,我希望 Parsed c dp 仅在 char == c 的结果中匹配,但实际上发生的是此函数返回的解析器可以匹配 任何 字符(即使 c 似乎被绑定到某个特定的 Char,作为一个函数参数)。
以下函数正常工作:
parserChar :: Char -> Parser Char
parserChar c = Parser ch where
   ch d = case dvChar d of
      Parsed char dp -> if char == c then Parsed char dp else NoParse
      _ -> NoParse

手动编写解析器来解析字母'a'也可以正确地工作,因为

case dvChar d of
   Parsed 'a' dp -> Parsed 'a' dp
   _ -> NoParse

只有当字符为'a'时才会返回成功。

那是为什么呢?你只能像这样匹配字面值吗(例如,尽管Char属于Eq类,但if char==c (..)仍然需要手动编码),还是我做错了什么?


顺便说一下,“仅匹配构造函数”规则绝对是一件好事,否则导入一个新的顶级定义(比如说)可能会极大地改变代码的语义! - Reid Barton
1个回答

7

是的,你只能匹配字面量。事实上,更好的思考方式是你只能匹配构造函数,而Int、Char、String等都有字面量构造函数。

请注意,你也可以混合使用大小写和守卫,并将其编写为(从记忆中):

parserChar :: Char -> Parser Char
parserChar c = Parser ch where
   ch d = case dvChar d of
      Parsed char dp | char == c -> Parsed char dp
      _ -> NoParse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接