Chadley Maggott
Chadley Maggott

Reputation: 366

Make function return different types haskell

I am completely new to haskell. I need a function that either returns an operator or returns an error message in the form of a string. For context I am building a Monadic Parser which accept doubles.

term'::Parser Double
term' = factor' `chainl1` mulop

addop, mulop :: Parser (Double -> Double -> Double)
mulop = do symbol "^" 
           return (**)
        +++ do symbol "*" 
               return (*)
        +++ do symbol "/"
               return (/)

addop = do symbol "+" 
           return (+)
        +++ do symbol "-"
               return (-)

The code above works well for returning the operator, however when I try expand on this by adding the error message I get compilation errors. Below is what I am attempting.

mulop :: Either (Parser (Double -> Double -> Double)) (Parser String)
mulop = do symbol "^" 
            return Left (**)
        +++ do symbol "*" 
               return Left (*)
        +++ do symbol "/" 
               return Left (/)
        +++ pure Right "ERROR MSG"

Upvotes: 0

Views: 130

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120711

That's only a single parser. It needs input to decide whether the output is an operator or an error-string. So the signature has to be

mulop :: Parser (Either (Double -> Double -> Double) String)

Actually there's something of a convention that when using Either as an exception-adding type, the error messages should be on the Left, so perhaps better make it

mulop :: Parser (Either String (Double -> Double -> Double))

In the implementation: be careful to get the syntax rules right. return and pure are just ordinary functions, not special keywords like return in procedural languages. So it needs to be return $ Left (**).

Also make sure you get the indentation right. I would align this thus:

mulop = do symbol "^" 
           return $ Right (**)
    +++ do symbol "*" 
           return $ Right (*)
    +++ do symbol "/" 
           return $ Right (/)
    +++ pure (Left "ERROR MSG")

Alternatively, don't use do notation. You don't really need anything monadic here, you can instead use the <$ operator:

mulop = (Right (**) <$ symbol "^")
    +++ (Right (*) <$ symbol "*")
    +++ (Right (/) <$ symbol "/")
    +++ pure (Left "ERROR MSG")

Upvotes: 3

Related Questions