Estaba intentando implementar una máquina de estado en Haskell. Una versión simplificada es la siguiente:Patrón de máquina de estado en Haskell: error de tipo infinito
En cualquier estado, puede alimentar a la máquina con un número entero y obtendrá un número entero. En el estado A, la máquina duplica sus entradas. En el estado B, la máquina simplemente te devuelve tu entrada. Siempre que vea un cero en cualquier estado, cambie al otro estado. De lo contrario, el estado no cambia.
Aquí está mi enfoque: simplemente haga que cada estado sea una función que devuelva tanto su salida como la función correspondiente al otro estado.
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]
Por desgracia, los tipos de a
y b
son infinitos y GHC se queja:
Occurs check: cannot construct the infinite type: t = t1 -> (t2, t)
¿Cuál es la manera de expresar este patrón en Haskell?
que podría, por supuesto, hacer algo como:
s 'a' x | x == 0 = (0,'b')
usando códigos de caracteres para el estado, pero el patrón de la función parece más elegante.
de tareas para el lector: haga que este patrón sea más común y cree una interfaz monádica para él. – fuz
En un punto de estilo: generalmente es más claro si dices 'a 0 = (0, b)' en lugar de 'a x | x == 0 = (0, b) '. – dave4420
En lugar de un código de carácter, sugiero usar un tipo de datos, como 'data State = A | B'. pero el primero también es bueno. – fuz