2016-04-26 9 views
0
type InterpreterMonad = StateT (Env, Env) (ErrorT String IO)()  

interpreter :: Stmts -> InterpreterMonad 
interpreter (Statements s EmptyStmts) = interpreteStmt s 
interpreter (Statements s stmts) = interpreteStmt s >>= \m -> (interpreter stmts) 


-- definicja funkcji 

interpreteStmt :: Stmt -> InterpreterMonad 
interpreteStmt (DefFun (VarName name) args typ begin statements end) = get >>= 
    \(envOut, (sInnerEnvFun, sInnerEnvEVal)) -> case (Map.lookup (VarName name) sInnerEnvFun) of 
     Nothing -> put ((envOut, ((Map.insert (VarName name) (DefFun (VarName name) args typ begin statements end) sInnerEnvFun), sInnerEnvEVal))) >>= \_ -> return() 
     (Just x) -> throwError "ee" 

こんにちは、私はなぜgetput関数を呼び出すことができます理解できません?ハスケルは "どこ"が国家であるかをどのように知っていますか?私は命令型プログラミングに有利な問題を抱えています。結局のところ、そのような関数をオブジェクトとして(メソッドとして)呼び出すか、引数で状態を渡す必要があります。モナド州と関数を取得

+2

私はあなたを知っていると思います(新しいアカウントを作成する必要はありません)) - ハスケルはあなたがいる文脈からそれを知っています - このように考える: 'put'はプレースホルダーのようです - あるアクションの - と '' = 'は、それが他の計算と接続します - それはそれが知っている方法です - 特定のタイプの' '= ''(または特定のタイプの' do'ブロック)...詳細は少し複雑ですが、おそらくそれを理解することは重要ではありません – Carsten

+0

これは、 'StateT'をあなたが今*何かを実行するのではなく、' runStateT'で実行するプラン* 。 'get'と' put'はその* plan *の中のただ一つのステップであり、* now *の状態と対話する関数ではありません。 –

答えて

1

あなたはStateモナド機能getputを使用してdo表記または>>=でそれらの配列を決定すると、あなたが最終的に使用されるローカル状態にアクセスし、修正するために(多くの場合、「アクション」と呼ばれる)「レシピ」を構築していますいくつかの特定の状態。たとえば:

increment = do 
    count <- get 
    put (count + 1) 

このアクションは、あなたが状態を渡してアクションを実行することができますStateインタフェースの一部で使用することができます。我々は証明するために、状態を返し、他の値を破棄され、execStateを使用します。

> execState increment 1 
2 

execStateは、それが修飾状態でアクションincrementを接続するものです。 incrementそれ自体は状態を含んでいませんが、後で評価する必要がある状態と対話するレシピに過ぎません。

1

Stateタイプは、(の一般化であるStateT)このようなものを実装されています。

newtype State s a = 
    State { -- A function that takes a state of type `s` and 
      -- produces a pair `(a, s)` of a result of type 
      -- `a` and a new state of type `s`. 
      runState :: s -> (a, s) 
      } 

このタイプはFunctorApplicativeとあなたが単純なもののうち、複雑なState値を組み立てることができるようMonadのためのインスタンスを持っています:

-- I won't write the code for these here 
instance Functor (State s) where ... 
instance Applicative (State s) where ... 
instance Monad (State s) where ... 

基本的には、Stateはのように見えるタイプの機能を連鎖ためのショートカットですがありますが、これらの値を明示的に値にする必要はありません。あなたが実際にあなたがこれらの操作のいずれかを使用s値を持つStateアクションを「フィード」する準備ができたら(あなたが望む結果のどの部分に応じて):

runState :: State s a -> s -> (a, s) 
evalState :: State s a -> s -> a 
execState :: State s a -> s -> s 

putget行い、その後、 State型が暗黙のうちにコード内を渡す "隠された"状態引数と対話します。実装は次のようなものです:

get :: State s s 
get = State (\s -> (s, s)) 

put :: s -> State s() 
put s = State (\_ -> ((), s)) 

これだけです!

関連する問題