2

Can someone please tell me what is wrong here? I can't figure out where the error is. I'm new to haskell, so I don't know every rule of syntax 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'  
2
  • 2
    Please post code, errors, sample data or textual output here as plain-text, not as images that can be hard to read, can’t be copy-pasted to help test code or use in answers, and are hostile to those who use screen readers. You can edit your question to add the code in the body of your question. Use the {} button to format any blocks of code, or indent with four spaces for the same effect. We can't run your screenshot as code. Commented Oct 6, 2017 at 20:19
  • 3
    Please post the error message, verbatim. Commented Oct 6, 2017 at 20:28

2 Answers 2

3

The problem is that the first where clause is taken as the end of the definition for parseS (s:xs). You're trying to add another guarded case afterwards, but the parser doesn't see it as attached to the same definition.

There's several ways you could fix this.

You could fix this by using a let ... in instead for 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'  

But there's an easier way to do it - just drop that where clause.

      | s == "+" = (xs'', Sum e e')
      | s == "*" = (xs'', Mul e e') where
                       (xs', e) = parseS xs 
                       (xs'', e') = parseS xs'  

The variables defined in a where clause are in scope for the entirety of a definition (for all guard cases), so your definition of xs'' can be reused for both cases.

Sign up to request clarification or add additional context in comments.

Comments

2

This is how Haskell sees your code:

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'

A where block attaches to a declaration, which in your case is the whole parseS definition.

The next line starting with | is seen as the start of a new declaration, which is invalid because you can't start a declaration with |.

The easiest fix is to stop using where for local bindings and use let instead, like this:

          | 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')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.