I have the following code:
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'
When I try to run it, I get an error saying "parse error on input '|'. The line it's talking about is this one:
...
(e',ss'') = parseExpr ss'
-> | s == "*" = (Mult e e',ss'') where
(e,ss') = parseExpr ss
...
I think I understand why. I would think it's because I have two lines above that are not shielded by guards, and that haskell then get's confused when there suddenly appears another guard below. But how can I then add additional guards after these cases?
I've tried using semicolons to separate new lines, but I'm very new with Haskell and therefore don't know much about its syntax.
There is no need to use braces (although of course you could). But you do need to be careful with indentation. It is not as hard as it may at first seem.
That being said, it is true that you cannot use where
inside a guarded expression. You have to use let
in such case, like this:
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'')
However, in your case here, the guard expressions are so simple they can be replaced with pattern matches. (And it is advisable to use the opportunity. Pattern matching is your best friend in Haskell.) In that case you use 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'