Я пытался реализовать конечный автомат в Haskell. Упрощенная версия:
В любом состоянии вы можете подать машине целое число и вернуть целое число. В состоянии A машина удваивает свои входы. В состоянии B машина просто вернет вам ваш вход. Всякий раз, когда вы видите нуль в любом состоянии, переходите в другое состояние. В противном случае состояние не изменяется.
Здесь мой подход: просто каждое состояние будет функцией, которая возвращает как свой вывод, так и функцию, соответствующую другому состоянию.
module Main where
a x | x == 0 = (0,b)
a x = (2*x, a)
b x | x == 0 = (0,a)
b x = (x, b)
evalstate s [] = []
evalstate s (x:xs) = (v:evalstate s' xs)
where (v,s') = s x
main :: IO ()
main = putStrLn $ show $ evalstate a [1,1,2,3,4,0,2,3,3]
К сожалению, типы для a
и b
бесконечны, и GHC жалуется:
Occurs check: cannot construct the infinite type: t = t1 -> (t2, t)
Каков способ выразить этот шаблон в Haskell?
Я мог бы, конечно, сделать что-то вроде:
s 'a' x | x == 0 = (0,'b')
используя коды символов для состояния, но шаблон функции кажется более элегантным.