由于我使用了守卫,我的代码导致解析错误
My code results in parse error because of my use of guards
我有以下代码:
parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
| s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
| s == "+" = (Sum e e',ss'') where
(e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
| s == "*" = (Mult e e',ss'') where
(e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
当我尝试 运行 它时,我收到一条错误消息“输入 '|' 时出现解析错误。它正在谈论的是这一行:
...
(e',ss'') = parseExpr ss'
-> | s == "*" = (Mult e e',ss'') where
(e,ss') = parseExpr ss
...
我想我明白为什么了。我会认为这是因为我上面有两条线没有被守卫屏蔽,然后当下面突然出现另一个守卫时 haskell 会感到困惑。但是在这些案例之后我该如何添加额外的警卫呢?
我尝试过使用分号来分隔新行,但我对 Haskell 还很陌生,因此对其语法了解不多。
不需要使用大括号(当然你可以)。但是你确实需要小心缩进。它并不像乍看起来那么难。
话虽这么说,但确实不能在受保护的表达式中使用 where
。在这种情况下你必须使用 let
,像这样:
parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
| s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
| s == "+" = let (e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
in (Sum e e',ss'')
| s == "*" = let (e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
in (Mult e e',ss'')
但是,在您的例子中,保护表达式非常简单,可以用模式匹配替换。 (建议利用这个机会。模式匹配是您在 Haskell 中最好的朋友。) 在这种情况下,您使用 where
。
parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
parseExpr ("-":ss) = (Min e,ss') where (e,ss') = parseExpr ss
parseExpr ("+":ss) = (Sum e e',ss'') where (e, ss' ) = parseExpr ss
(e',ss'') = parseExpr ss'
parseExpr ("*":ss) = (Mult e e',ss'') where (e, ss' ) = parseExpr ss
(e',ss'') = parseExpr ss'
我有以下代码:
parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
| s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
| s == "+" = (Sum e e',ss'') where
(e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
| s == "*" = (Mult e e',ss'') where
(e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
当我尝试 运行 它时,我收到一条错误消息“输入 '|' 时出现解析错误。它正在谈论的是这一行:
...
(e',ss'') = parseExpr ss'
-> | s == "*" = (Mult e e',ss'') where
(e,ss') = parseExpr ss
...
我想我明白为什么了。我会认为这是因为我上面有两条线没有被守卫屏蔽,然后当下面突然出现另一个守卫时 haskell 会感到困惑。但是在这些案例之后我该如何添加额外的警卫呢?
我尝试过使用分号来分隔新行,但我对 Haskell 还很陌生,因此对其语法了解不多。
不需要使用大括号(当然你可以)。但是你确实需要小心缩进。它并不像乍看起来那么难。
话虽这么说,但确实不能在受保护的表达式中使用 where
。在这种情况下你必须使用 let
,像这样:
parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
| s == "-" = let (e,ss') = parseExpr ss in (Min e,ss')
| s == "+" = let (e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
in (Sum e e',ss'')
| s == "*" = let (e,ss') = parseExpr ss
(e',ss'') = parseExpr ss'
in (Mult e e',ss'')
但是,在您的例子中,保护表达式非常简单,可以用模式匹配替换。 (建议利用这个机会。模式匹配是您在 Haskell 中最好的朋友。) 在这种情况下,您使用 where
。
parseExpr :: [String] -> (Ast,[String])
parseExpr [] = error "Incorrect"
parseExpr (s:ss) | all isDigit s = (Tall (read s),ss)
parseExpr ("-":ss) = (Min e,ss') where (e,ss') = parseExpr ss
parseExpr ("+":ss) = (Sum e e',ss'') where (e, ss' ) = parseExpr ss
(e',ss'') = parseExpr ss'
parseExpr ("*":ss) = (Mult e e',ss'') where (e, ss' ) = parseExpr ss
(e',ss'') = parseExpr ss'