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?
I need to call
foo
withf
andarg
making sure that they are notLeft
.
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
).
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
精彩评论