State モナドの詳細を調べるために、単純な状態モナド関数の完全な desugar バージョンを自分で作成して、Haskell で「get」は実際に初期状態を /get/ する方法は?で始まった考えを完成させようとしています。、J Cooperによる回答。
状態モナド関数の例では、(概念的に) 入力が (v, s) の場合、出力は (s, v) になるように、状態と入力値を単純に交換します。3 つの変換を示します。最初は do 表記から desugared >>= および >> へ、次にこれらの演算子を関数の位置に配置し、最後にそれらを置き換えて get/put をそれらの定義で試みます。
「do」バージョンと最初の 2 つの翻訳は機能しますが、最終的な翻訳は機能しません。問題:
- モジュールをロードすると、GHCi は z1 がスコープ外であることを報告します。
- >> 翻訳で渡される引数の省略を表す方法を正確に理解していません。
これらはどのように修正する必要がありますか?
FWIW、現在の Haskell プラットフォーム (GHC 7.4.2)。
ありがとう!
-- simpleswap
import Control.Monad.State
-- =============================================
-- 'Do' version
simpleswap1 :: String -> State String String
simpleswap1 inp = do
z1 <- get
put inp
return z1
-- =============================================
-- Desugared to >>= and >>
simpleswap2 :: String -> State String String
simpleswap2 inp =
get >>=
\z1 -> put inp >>
return z1
-- =============================================
-- >>= and >> changed to function position
simpleswap3 :: String -> State String String
simpleswap3 inp =
(>>=) get
(\z1 -> (>>) (put inp) (return z1) )
-- =============================================
-- Attempt to translate >>=, >>, get and put
simpleswap4 :: String -> State String String
simpleswap4 inp =
state $ \s1 ->
-- (>>=)
let (a2, s2) = runState ( {- get -} state $ \sg -> (sg,sg) ) s1
in runState (rhs1 a2) s2
where
rhs1 a2 = \z1 ->
-- (>>)
state $ \s3 ->
let (a4, s4) = runState ( {- put inp -} state $ \_ -> (inp, ()) ) s3
in runState (rhs2 a4) s4
where
rhs2 a4 = return z1
-- =============================================
main = do
putStrLn "version 1004"
let v = "vvv"
let s = "sss"
putStrLn ("Before val: " ++ v ++ " state: " ++ s)
let (v2, s2) = runState (simpleswap4 v) s
putStrLn ("After val: " ++ v2 ++ " state: " ++ s2)
-- =============================================