爲了研究國家monad的細節,我試圖創建一個簡單的狀態monad函數的完全desugared版本,完成在How does 'get' actually /get/ the initial state in Haskell?開始的想法,在J Cooper回答。哈斯克爾:試圖desugar簡單的國家monad得到並把
示例狀態monad函數簡單地交換狀態和輸入值,所以(概念上)如果輸入是(v,s),那麼輸出是(s,v)。我展示了三種翻譯,第一種是從符號到desugared >> =和>>,然後將這些操作符置於函數位置,最後嘗試替換它們並獲取/放入它們的定義。
'做'版本和前兩個翻譯工作,但最後的翻譯沒有。問題:
- 加載模塊後,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)
-- =============================================
太棒了!非常感謝您糾正我的嘗試,並詳細說明這些更改。非常感激! – gwideman 2013-03-03 11:24:53