StateTだとぉ〜!

ちょっと どうやってまとめていいか 整理できてゐないのだが
とにかく今 感動してゐるので 書き殘しておきたい

ゲーム制作でなくとも アプリかなんかつくるんであれば
色々と画面に表示(描画)しながら 何らかの「状態」を變化させていくだらう

Haskell では その「状態」を表す データ型をつくって それを函數に渡しながら そのデータ型に基いた 新たなデータをつくり 「状態」を變化させていったりできる

だが つねに 「今」の状態を示すデータを 受けとって それをもとに 新しい「状態」データを作成し また それを次の函數に渡していく〜といふのは なんといふか 「必ずやる」ことなのに 毎回函數に加へなくてはならない情報であって やはり 「なんか もっと うまいやり方はないのかな〜」などと思ってしまふ

そんで 本などを見ると
State s モナド なんていふものが書いてある
これを利用すると 「状態」を簡単に扱へる といふことらしいのだが
いまいち 私には その具体的な使ひ方が 腑に落ちなかった

とにかく使ってみやう といふことで SDL2を使ってイメージの讀み込みと ウインドウ表示だけをするコードを書き 色々と實驗してみた

しかし うまくいかない

State s モナド は (State 状態 結果) を返す函數と 初期の状態を runState といふ函數に與へることで機能する
だけど runState に與へたい函數は 単に状態を變化させる といふだけでなく 様々な出力に對應する つまり IO型を扱ふ函數であってほしい〜といふか さうでなくては困るのだ

それを念頭に Hackage の Control.Monad.State.Strict のドキュメントとにらめっこしてゐて
StateT についての項目をながめてゐた

newtype StateT s (m :: * -> *) a

s - The state.
m - The inner monad.
と書かれてゐる
もしかして m を IOにできるってこと?
StateT モナドを實行する runStateT といふ函數もある
・・・もしかして・・・
コードを書いてみた (一部を載せる)

module App(appMain) where

import Control.Monad.State.Strict (runStateT)
import MySDL.Load (loadFiles)
import MySDL.Loop (loop)
import MySDL.Init (withInit)
import MySDL.Video (withVideo)
import MyData (initWorld)

appMain :: IO ()
appMain =
  withInit $ do
    imageS <- loadFiles
    withVideo $
      \renderer -> runStateT (loop renderer imageS) initWorld
module MySDL.Loop where

import Control.Monad.State.Strict (StateT,get,put)
import Control.Monad.IO.Class (liftIO)
import SDL.Video.Renderer (Renderer,Surface)
import SDL.Time (delay)
import MyData (World(..), Input(..),  delayTime)
import Event (inputEvent)

loop :: Renderer -> [Surface] -> StateT World IO ()
loop re imageS = do
  inp <- liftIO inputEvent
  wld <- get
  let newWorld = wld{abc=abc wld + 1}
  liftIO (print (abc wld))
  put newWorld
  delay delayTime
  if inp==QIT then return () else loop re imageS

今回實驗で使った「状態」は Worldといふ型で abc=0, def=1 といふ値を初期値とする 單純なものだ
これを メインループ上で取り出し abcに1を加へてターミナルに表示させることができた
ここで loop函數は 状態を表す引數をもってゐない
それでも get函數で 状態を取得し put函數で 状態を書き込むことができる! この函數のなかで IOアクションを實行するときは liftIO を適用すればよい

これで 「状態」をかなりスマートに扱ふことができるやうな氣がする〜

コード全体は

github.com