我正在從“LYAH”學習 Haskell 并進入了 State monad。作為一個練習,我正在努力實作一個簡單的“虛擬 CPU”。state monad 似乎很適合這個,但我不知道如何使用它。這是我目前擁有的一個非常精簡的示例(沒有狀態單子):
data Instruction = Incr | Decr | Halt
data Computer = Computer { program :: [Instruction],
acc :: Int,
pc :: Int,
halted :: Bool
}
main = do
let comp = Computer { program = [Incr, Decr, Incr, Incr, Halt]
, acc = 0
, pc = 0
, halted = False
}
execute comp
execute :: Computer -> IO ()
execute comp = do
let (output, comp') = step comp
putStrLn output
case halted comp' of
False -> execute comp'
True -> return ()
step :: Computer -> (String, Computer)
step comp = let inst = program comp !! pc comp
in case inst of
Decr -> let comp' = comp{ acc = acc comp - 1,
pc = pc comp 1 }
output = "Increment:"
" A = " (show $ acc comp')
" PC = " (show $ pc comp')
in (output, comp')
Incr -> let comp' = comp{ acc = acc comp 1,
pc = pc comp 1 }
output = "Decrement:"
" A = " (show $ acc comp')
" PC = " (show $ pc comp')
in (output, comp')
Halt -> let comp' = comp{halted = True}
output = "HALT"
in (output, comp')
我的step函式看起來像 state monad,但我在這里看不到如何使用它。會適用嗎?它會簡化這段代碼,還是這個例子更好?
uj5u.com熱心網友回復:
絕對地。step可以很機械地翻譯:
import Control.Monad.Trans.State
step :: State Computer String
step = do
comp <- get
case program comp !! pc comp of
Decr -> do
let comp' = comp { acc = acc comp - 1
, pc = pc comp 1 }
put comp'
return $ "Increment:"
" A = " (show $ acc comp')
" PC = " (show $ pc comp')
Incr -> do
let comp' = comp { acc = acc comp 1
, pc = pc comp 1 }
put comp'
return $ "Decrement:"
" A = " (show $ acc comp')
" PC = " (show $ pc comp')
Halt -> do
put $ comp{halted = True}
return "HALT"
(這些仍然有點尷尬。可以通過使用庫中的let comp' = ...狀態欄位修飾符使其更像命令式。)lens
您可能會注意到,這State實際上只是StateT變壓器的一種特殊化,而我使用的所有功能都不是專門針對此的。即您可以立即將簽名概括為
step :: Monad m => StateT Computer m String
事實證明,這對 . 派上用場execute,因為您將狀態修改與IO副作用穿插在一起——這正是轉換器的用途。
import Control.Monad.IO.Class
execute :: StateT Computer IO ()
execute = do
output <- step
liftIO $ putStrLn output
comp <- get
case halted comp of
False -> execute
True -> return ()
最后,在main你只需要
main = do
let comp = ...
evalStatT execute comp
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/474042.html
標籤:哈斯克尔
上一篇:從條件資料串列中獲取資料
下一篇:Haskell陣列條件混亂
