有人可以告诉我这里有什么问题吗?我无法弄清楚错误的位置。我是haskell的新手,所以我不知道每个语法规则atm。
parseS (s:xs) | all isDigit s = (xs, Lit (read s))
| s == " " = parseS xs
| s == "-" = let (remainder, e) = parseS xs in (remainder, Sub e)
| s == "+" = (xs'', Sum e e') where
(xs', e) = parseS xs
(xs'', e') = parseS xs'
| s == "*" = (xs'', Mul e e') where <- parse error on input on this line
(xs', e) = parseS xs
(xs'', e') = parseS xs'
答案 0 :(得分:3)
问题是第一个where
子句被视为parseS (s:xs)
定义的结尾。您之后尝试添加另一个受保护的案例,但解析器并未将其视为附加到相同的定义。
有几种方法可以解决这个问题。
可以使用let ... in
代替s == "+"
| s == "+" = let (xs', e) = parseS xs
(xs'', e') = parseS xs
in (xs'', Sum e e')
| s == "*" = (xs'', Mul e e') where
(xs', e) = parseS xs
(xs'', e') = parseS xs'
但是有一种更简单的方法 - 只需删除where
子句。
| s == "+" = (xs'', Sum e e')
| s == "*" = (xs'', Mul e e') where
(xs', e) = parseS xs
(xs'', e') = parseS xs'
where
子句中定义的变量适用于整个定义(适用于所有保护案例),因此xs''
的定义可以在两种情况下重复使用。
答案 1 :(得分:2)
这就是Haskell看到你的代码的方式:
parseS (s:xs)
| all isDigit s = (xs, Lit (read s))
| s == " " = parseS xs
| s == "-" = let (remainder, e) = parseS xs in (remainder, Sub e)
| s == "+" = (xs'', Sum e e')
where
(xs', e) = parseS xs
(xs'', e') = parseS xs'
| s == "*" = (xs'', Mul e e')
where
(xs', e) = parseS xs
(xs'', e') = parseS xs'
where
块附加到声明,在您的情况下是整个parseS
定义。
以|
开头的下一行被视为新声明的开头,由于您无法使用|
启动声明,因此该声明无效。
最简单的解决方法是停止使用where
进行本地绑定,并使用let
代替,如下所示:
| s == "+" =
let
(xs', e) = parseS xs
(xs'', e') = parseS xs'
in
(xs'', Sum e e')
| s == "*" =
let
(xs', e) = parseS xs
(xs'', e') = parseS xs'
in
(xs'', Mul e e')