Advent of code #2 Haskell solution
Use Control.Lens for code this stateful. (Control.Lens.TH must be used to define Machine.) May as well leave out type signatures this homogenous. Control.Monad.Loops often helps against explicit monadic recursion.

opReadAt target = uses mState $ (`index` target)
opReadNext = mPos &lt;&lt;+= 1 &gt;&gt;= opReadAt
opWrite target what = mState %= update target what

opBin op = do
    a &lt;- opReadNext &gt;&gt;= opReadAt
    b &lt;- opReadNext &gt;&gt;= opReadAt
    target &lt;- opReadNext
    opWrite target $ op a b 

opcode 1 = opBin (+)
opcode 2 = opBin (*)
opcode 99 = isDone .= True

runCode = (opReadNext &gt;&gt;= opCode) `untilM_` use isDone

evalWith :: Int -&gt; Int -&gt; Machine -&gt; Int
evalWith noun verb = evalState $ do
    opWrite 1 noun
    opWrite 2 verb
    runCode
    opReadAt 0