Obtenga valor de IO en lugar del cálculo en sí
Siendo bastante nuevo en Haskell, actualmente estoy tratando de mejorar mis habilidades escribiendo un intérprete para un lenguaje de juguete simple e imperativo.
Una de las expresiones en este idioma esinput
, que lee un solo entero de la entrada estándar. Sin embargo, cuando asigno el valor de esta expresión a una variable y luego uso esta variable más tarde, me parece que realmente almacené elcálculo de leer un valor en lugar del valor de lectura en sí. Esto significa que p. Las declaraciones
x = input;
y = x + x;
hará que el intérprete invoque el procedimiento de entradaTres veces en lugar de uno.
Internamente en el módulo evaluador, uso unMap
para almacenar los valores de las variables. Como necesito tratar con IO, esto se ve envuelto en unIO
mónada, como inmortalizada en el siguiente ejemplo mínimo:
import qualified Data.Map as Map
type State = Map.Map String Int
type Op = Int -> Int -> Int
input :: String -> IO State -> IO State
input x state = do line <- getLine
st <- state
return $ Map.insert x (read line) st
get :: String -> IO State -> IO Int
get x state = do st <- state
return $ case Map.lookup x st of
Just i -> i
eval :: String -> Op -> String -> IO State -> IO Int
eval l op r state = do i <- get l state
j <- get r state
return $ op i j
main :: IO ()
main = do let state = return Map.empty
let state' = input "x" state
val <- eval "x" (+) "x" state'
putStrLn . show $ val
La segunda línea en elmain
la función simula la asignación dex
, mientras que la tercera línea simula la evaluación del binario+
operador.
Mi pregunta es: ¿cómo puedo evitar esto, de modo que el código anterior solo ingrese una vez? Sospecho que es elIO
-envoltura que causa el problema, pero como estamos tratando con IO, ¿no veo salida de eso ...?