2011-09-23 4 views
2
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 

Мне нужно позвонить foo с f и arg убедившись, что они не являются Left.Снизить шаблон

Могу ли я уменьшить соответствие шаблонов и вместо этого использовать привязки и другие операции с монадами?

+0

Короткий ответ: да, есть монада. –

ответ

1

Вы можете использовать do. Ваш код проверяет arg до f и foo, как представляется, возвращает ErrorOrValue, поэтому его не нужно поднимать в Monad. Кроме того, as, который передается в foo, является извлеченным из Partial, а не аргументом evaluateExpression. Вот какой-то полностью непроверенный код:

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 
5

Мне нужно позвонить foo с f и arg убедившись, что они не являются Left.

Для этого вы можете использовать пример Applicative для Either.

foo <$> f <*> arg 

или

liftA2 foo f arg 

Если f и arg являются Right значения, это будет извлекать те, применять foo к ним и дать ответ обратно в Right конструктор. Если f или arg - значения Left, это значение будет возвращено (в пользу одного из f, если оба они являются Left).

Смежные вопросы