素朴かつ関数的に(ここでは、do構文を使わない、配列を使わない、程度の意味)考えるなら、
性能はともかく、こんな感じでしょうか。(詳細は書いてないので動かしてませんが。^^;)
module Main where
import Data.Char ( toUpper )
main :: IO ()
main = print . lastState . run . load . map toUpper . filter ('+' /=)
=<< readFile "day08.txt"
type Code = (OP, Arg)
data OP
= NOP
| ACC
| JMP
deriving (Eq, Show, Read)
type Arg = Int
type Offset = Int
type Mem = ([Code], Code, [Code])
derefPC :: Mem -> Code
derefPC (_, c, _) = c
jump :: Offset -> Mem -> Mem
jump offset mem = undefined
type Acc = Int
updAcc :: Offset -> Acc -> Acc
updAcc offset acc = acc + offset
type Count = Int
updCount :: Count -> Count
updCount count = succ count
type Output = String
type VMState = (Mem, Acc, Count, Output)
isFinalState :: VMState -> Bool
isFinalState vm = undefined
load :: String -> VMState
load src = case map toCode (lines src) of
h : t -> (([], h, t), 0, 0, "")
toCode :: String -> Code
toCode ln = case words ln of
op : num : _ -> (read op, read num)
run :: VMState -> [VMState]
run st = st : if isFinalState st then [] else run (step st)
step :: VMState -> VMState
step vm = execute (decode (fetch vm)) vm
fetch :: VMState -> Code
fetch (mem, _, _, _) = derefPC mem
decode :: Code -> (VMState -> VMState)
decode code vm = case code of
(op, offset) -> undefined
execute :: (VMState -> VMState) -> VMState -> VMState
execute = id
lastState :: [VMState] -> (Acc, Count, Output)
lastState states = case last states of
(_,acc,cnt,msg) -> (acc, cnt, msg)