私はCombine state with IO actionsのアドバイスに従って、IOモナドと共にAppStateを構築しようとしています。私が得たことは次のとおりです。IOと一緒にStateTモナドを実際にどのように実行するのですか?
module Main where
import Control.Monad.State
import Control.Monad.Trans
data ST = ST [Integer] deriving (Show)
type AppState = StateT ST IO
new = ST []
append :: Integer -> State ST()
append v = state $ \(ST lst) -> ((), ST (lst ++ [v]))
sumST :: State ST Integer
sumST = state $ \(ST lst) -> (sum lst, ST lst)
script = do
append 5
append 10
append 15
sumST
myMain :: AppState()
myMain = do
liftIO $ putStrLn "myMain start"
let (res, st) = runState script new
liftIO $ putStrLn $ show res
liftIO $ putStrLn "myMain stop"
main = runStateT myMain (ST [15])
私が得意ではない部分があります。それは私が大いに悩まされているのです。script
とmyMain
とmain
です。また、私はrunState
をmyMain
の中で実行しなければならないこと、そして私の最初の状態を私の主な機能のrunStateT
に供給しなければならないことが気になります。 myMainのポイント全体がmyMainとappendを直接実行することができるので、myMain関数で直接「スクリプト」を作成したいと思っています。
myMain :: AppState()
myMain = do
liftIO $ putStrLn "myMain start"
append 5
append 10
append 15
r <- sumST
liftIO $ putStrLn $ show res
liftIO $ putStrLn "myMain stop"
main = runState myMain
私はモナド変換子のポイントはので、私は関数の中で私のStateモナド操作を実行する(上記のような)とにIO操作を持ち上げることができたと思っていた:私は、私は代わりに、これを行うことができるはずだと思いますその機能。間接指示のレイヤーの1つを削除できるように、これをすべて設定する正しい方法は何ですか? (私は解決策をフラグが付けられている)ダニエルのソリューションに加えて
、私はまた、状況にいくつかの光を当てるかもしれないいくつかのバリエーションを発見しました。まず、最終myMainの実装とメイン:今すぐ
myMain :: AppState()
myMain = do
liftIO $ putStrLn "myMain start"
append 5
append 10
append 15
res <- sumST
liftIO $ putStrLn $ show res
liftIO $ putStrLn "myMain stop"
main = runStateT myMain new
、ダニエルのに加えて、追記やsumSTの様々な実装、:
append :: Integer -> AppState()
append v = state $ \(ST lst) -> ((), ST (lst ++ [v]))
sumST :: AppState Integer
sumST = state $ \(ST lst) -> (sum lst, ST lst)
と(ノートのみ型宣言の変更、実際にはあなたは完全に型宣言を省略することができます!)
append :: MonadState ST m => Integer -> m()
append v = state $ \(ST lst) -> ((), ST (lst ++ [v]))
sumST :: MonadState ST m => m Integer
sumST = state $ \(ST lst) -> (sum lst, ST lst)
AppState/StateTモナドはと同じではないことを私に起こりました基本的な状態のモナドであり、私は状態のモナドに対してsumSTとappendの両方をコーディングしていました。ある意味では、彼らはStateTモナドにも持ち込まなければなりませんでしたが、正しい考え方は、をモナドで実行する必要があったということです(したがって、runState script new
)。
私はそれを完全に得ることはできませんが、私はしばらくそれに取り組み、MonadStateコードを読んで、最終的に私の頭の中でこれについて何か書きます。
ああ、 'state'は私が想定していたより多相です。これは私の頭の中に何らかの理由で' 'State'コンストラクタをそれ以上エクスポートしないという謝罪であったからです。 TIL! –