= Solution
Compose the three parsing stages using the supplied <fold>, and accept only when no suffix remains:
``
eval :: String -> Maybe Int
eval input = foldMaybe first Nothing (parseInt input)
where
first (a,rest) = foldMaybe (second a) Nothing (parseOp rest)
second a (op,rest) = foldMaybe (finish a op) Nothing (parseInt rest)
finish a op (b,rest)
| null rest = Just (apply op a b)
| otherwise = Nothing
apply '+' a b = a+b
apply '-' a b = a-b
apply '*' a b = a*b
apply '/' a b = a `div` b
apply _ _ _ = error "unreachable: parseOp rejected this operator"
``
Every failed intermediate <parser> is converted to `Nothing` by `foldMaybe`. Checking `null rest` rejects both a second operation and trailing letters. In particular, integer division makes `eval "34/4" = Just 8`. As permitted by the question, division by zero is outside the specified inputs; the bounded-`Int` proviso also applies to arithmetic results.
Back to article page