【发布时间】:2014-03-21 20:20:39
【问题描述】:
作为 Haskell 的新手,我目前正在尝试通过为一种简单的命令式玩具语言编写解释器来提高我的技能。
这种语言中的一个表达式是input,它从标准输入中读取一个整数。但是,当我将此表达式的值分配给一个变量,然后稍后再使用此变量时,似乎我实际上存储了读取值的计算,而不是读取的值本身。这意味着例如声明
x = input;
y = x + x;
将导致解释器调用输入过程三次次而不是一次。
在评估器模块内部,我使用Map 来存储变量的值。因为我需要处理 IO,所以它被包裹在一个 IO monad 中,如下面的最小示例所示:
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
main 函数中的第二行模拟x 的赋值,而第三行模拟二元+ 运算符的求值。
我的问题是:如何解决这个问题,以使上面的代码只输入一次?我怀疑是 IO-wrapping 导致了问题,但是当我们处理 IO 时,我看不出有什么办法......?
【问题讨论】:
标签: haskell functional-programming monads interpreter io-monad