user181351
user181351

Reputation:

Reduce the pattern matching

type ErrorOrValue = Either InterpreterError Value 

evaluateExpression :: [Value] -> IR.Expression -> ErrorOrValue

evaluateExpression as (IR.Application l r) 
    | Left _ <- arg = arg
    | Right (Partial ac b as) <- f = foo as f arg
    | Right _ <- f = Left NonFunctionApplication
    | otherwise = f
    where
        f = evaluateExpression as l >>= forceValue
        arg = evaluateExpression as r

I need to call foo with f and arg making sure that they are not Left.

Can I reduce the pattern matching and instead use binds and other monad operations?

Upvotes: 2

Views: 218

Answers (2)

pat
pat

Reputation: 12749

You can use do. Your code checks arg before f, and foo appears to return an ErrorOrValue, so it does not need to be lifted into the Monad. Also, the as that is passed to foo is that extracted from the Partial, not the argument to evaluateExpression. Here is some completely untested code:

type ErrorOrValue = Either InterpreterError Value 

evaluateExpression :: [Value] -> IR.Expression -> ErrorOrValue

evaluateExpression as (IR.Application l r) =
    do arg <- evaluateExpression as r
       f <- evaluateExpression as l >>= forceValue
       case f of
           Partial ac b as -> foo as f arg
           otherwise -> Left NonFunctionApplication

Upvotes: 1

hammar
hammar

Reputation: 139860

I need to call foo with f and arg making sure that they are not Left.

For this, you can use the Applicative instance for Either.

foo <$> f <*> arg

or

liftA2 foo f arg

If f and arg are Right values, this will extract those, apply foo to them and give the answer back in a Right constructor. If either f or arg are Left values, that value will be returned (favoring the one from f if both are Left).

Upvotes: 5

Related Questions