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 ...?

Respuestas a la pregunta(4)

Su respuesta a la pregunta