Haskell'de yazılmış ilkel tercümanım var. Bu yorumlayıcı return
ifadelerini (see my previous question) doğru şekilde işleyebilir.Süreklilik ve durum monad transformatörler oluşturmak için doğru yolu
Şimdi global durumu çevirmenime eklemek istiyorum. Bu durum, global koddan veya işlev kodu 'dan (runCont
ile return
mantığını sağlamak için çalıştırılır) değiştirilebilir.
import Control.Monad.Cont
import Control.Monad.State
type MyState = String
data Statement = Return Int | GetState | SetState MyState | FuncCall [Statement] deriving (Show)
data Value = Undefined | Value Int | StateValue MyState deriving (Show)
type Eval a = StateT MyState (Cont (Value, MyState)) a
runEval ::(Eval Value) -> MyState -> (Value, MyState)
runEval eval state = runCont (runStateT eval state) id
evalProg :: [Statement] -> Value
evalProg stmts = fst $ runEval (evalBlock stmts) $ ""
evalBlock :: [Statement] -> Eval Value
evalBlock [] = return Undefined
evalBlock [stmt] = evalStatment stmt
evalBlock (st:stmts) = evalStatment st >> evalBlock stmts
evalStatment :: Statement -> Eval Value
evalStatment (Return val) = do
state <- get
lift $ cont $ \_ -> (Value val, state)
evalStatment (SetState state) = put state >> return Undefined
evalStatment (FuncCall stmts) = do
-- I don't like this peace of code
state <- get
(value, newState) <- return $ runEval (evalBlock stmts) $ state
put newState
return value
evalStatment GetState = get >>= return . StateValue
test2 = evalProg [SetState "Hello", FuncCall [SetState "Galaxy", Return 3], GetState] -- result is StateValue "Galaxy"
Bu kod çalışıyor ama bu kodun evalStatment (FuncCall stmts)
bölümünü sevmiyorum:
kod burada sunulmuştur. Şu anki çevirmen durumunu runEval
işlevine, 'a iletiyorum ve sonra değiştirilmiş duruma geri dönün ve yeni çevirmen durumu olarak ayarlayın.
Bu kodu iyileştirmek mümkün müdür? Bir şekilde fonksiyonun kodunu (FuncCall
) yorumlayıcının durumu üzerinde çalışabilir miyim (geçerli durum ve çalışma fonksiyonunun kodunu almadan ve tercümanın yeni durumunu açıkça belirten)?
Sadece diziye ihtiyacınız var mı? :: Monad m => [m a] -> m [a] '? Muhtemelen 'liftM last :: Monad m => m [a] -> m a' tarafından takip ediliyor? –