6
我正在做一個項目,需要我寫一個小型的解釋器。這些指令具有簡單的樹形結構,其中一個命令具有暫停執行的效果。所以在下面的例子中,「baz」從不打印。這是對ContT的適當使用嗎?
import Control.Monad.Cont
data Instruction = Print String | Halt | Block [Instruction]
deriving (Eq, Show)
instructions =
[ Print "foo"
, Block
[ Print "bar"
, Halt
]
, Print "baz"
]
main :: IO()
main = runContT (callCC $ interpret instructions)
(const $ pure())
interpret [] k = pure()
interpret (a:as) k = case a of
Print str -> liftIO (putStrLn str) >> interpret as k
Block ins -> interpret ins k >> interpret as k
Halt -> k()
這是我第一次在我的一個項目中看到ContT
的潛在用途。我想知道這是否適合使用它,或者我可能忽略了一個更簡單的解決方案。
如果你唯一的跳躍指令是「停止」,你可以使用'Except'更簡單。除此之外,延續monad並不適合於一般的口譯人員。 – Alec
這很好。如果我們不需要改變'k',如上所述,我們可以嘗試在整個列表中使用'traverse_'或'mapM_'。請注意,由於「早期返回」效應,'k()'與'k()>> ...'是相同的,因此遍歷整個列表(懶惰)應該是等價的。 – chi