許多的程式應用情境,是要依賴隨著時間或是運算而不停變換的狀態而進行。Haskell 中沒有變數,數值都是不可變的。
Haskell 要達到這種需求,同樣也是靠函數。藉由傳入 state 作為輸入參數,經過運算後回傳最後的結果以及更新後的 mewState。
原本的 state 並沒有被修改到,而我們也同樣達到了根據 state 做計算並且變換 state 的目的了
而在 Haskell 中,這種需要處理狀態性問題時,常用到的工具就是 State monad。
範例
一般會用躑骰子當範例
|
|
目前這種模擬躑五次骰子的方法看起來很不舒服,原因在於 generator 他必須手動取出和傳入,多了很多重複的步驟。
如果使用了 State monad,我們就可以將 generator 作為 state 來改善目前的範例。
定義 State monad
|
|
State
包裹著一個函數型別為s -> (a, s)
。其意義就是如一開始所說的,傳入 state,經過運算回傳結果以及新的 state。
State monad 的Functor
Applicative
Monad
instance 我們可以如此定義
|
|
從實作中可以看到 state 會不斷的更新然後傳遞下去。
Methods
一般的 State monad 還會提供幾個方便的 method
|
|
範例改寫
|
|
如此一來可以定義“躑 n 次骰子”的函數,而且看起來還比原先範例更為精簡。
結語
如同 Reader monad,一般在使用時,同樣會直接使用現成的 library 像 mtl
或transformers
。
可以去看看這些 library 是如何實作的,藉此來學習。
此外通常看到或是使用時,因為會需搭配其他的 Monad 一起使用,並不會用State
而是使用StateT
。而去看原始碼可以發現 State s a
其實也就是StateT s Identity a
的type alias。