Building a Turing Machine Simulator With Ruby (Part 1)
reinh.com
reinh.com
One mildly interesting aspect of simulating a Turing machine is how you deal with the doubly-infinite tape. Haskell already has support for singly-infinite lists, so you can implement it very easily:
data Command s v = Halt | GoLeft s v | GoRight s v
type Tape v = ([v], [v]) -- Both lists must be infinite.
type Next s v = s -> v -> Command s v
turing :: Next s v -> s -> Tape v -> Tape v
turing f s t@(l:ls, r:rs) =
case f s r of
GoLeft s' v -> turing f s' (ls, l:v:rs)
GoRight s' v -> turing f s' (v:l:ls, rs)
Halt -> t
If your Turing machine simulator is much more verbose than this, you are probably doing it wrong.As an example, here's a Turing machine that counts the parity of the rightward run of 1s from the tape head's starting position, writes it to the tape, and halts:
data Bit = Zero | One deriving Show
data ParityState = Even | Odd | Done
parityTM = turing next Even
where next Even One = GoRight Odd Zero
next Odd One = GoRight Even Zero
next Even Zero = GoRight Done Zero
next Odd Zero = GoRight Done One
next Done _ = Halt
To test it, here's a helper function that converts a Haskell integer into a tape containing all 0s to the left, a run of n 1s to the right, followed by all 0s, and runs the Turing machine on it: parity :: Int -> Bit
parity n = head $ fst $ parityTM (repeat Zero, replicate n One ++ repeat Zero)