newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
type State s = StateT s Identity
class Monad m => MonadState s m | m -> s
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
type State s = StateT s Identity
class Monad m => MonadState s m | m -> s
從前,有一個State
類型:
-- Not the current definition.
newtype State s a = State {runState :: s -> (a, s)}
State s a
值是,在本質上,採取的狀態,併產生一個結果,並更新狀態的功能。合適的Functor
,Applicative
和Monad
實例使得有可能通過使得元組混排需要處理輸出隱式來更方便地組合這些函數。與操作狀態操作的幾個基本的幫助...
get = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)
...它是可能避免的潛在s -> (a, s)
類型的任何提及,並編寫代碼感覺狀態。
StateT s
是單子變壓器State s
之後圖案化:
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
這種變壓器的頂上添加鹼單子,m
上述狀態的處理能力。它附帶Functor
,Applicative
和Monad
實例,以及get
和put
的版本。
如果m
,基地單子,在StateT s m
是Identity
,僞仿...
newtype Identity a = Identity {runIdentity :: a}
...我們得到的東西等同於普通的舊State s
。如此,變壓器將State
定義爲同義詞...
type State s = StateT s Identity
...而不是作爲一個單獨的類型。
至於MonadState
,它迎合了兩種不同的需求。首先,我們可以使用monad變壓器機器將StateT s m
作爲變壓器堆棧中某個其他變壓器的基本monad(任意示例:MaybeT (StateT Int IO)
)。在這種情況下,使用get
和put
時,需要lift
從MonadTrans
。直接在這樣的情況下使用該業務的一種方式是通過MonadState
:它提供了他們作爲方法...
-- Abridged class definition.
class Monad m => MonadState s m | m -> s where
get :: m s
put :: s -> m()
state :: (s -> (a, s)) -> m a
...這樣我們就可以對涉及StateT
變壓器的任意組合,我們有興趣的情況下, 。
instance Monad m => MonadState s (StateT s m) where -- etc.
instance MonadState s m => MonadState s (MaybeT m) where -- etc.
-- And so forth
其次,如果我們希望有一個比變壓器不同的實現的狀態單子,我們可以把它的MonadState
一個實例,讓我們保持相同的基本操作,併爲只要我們寫類型簽名根據MonadState
計算,如果需要,可以更容易地更改實現。
State
是你的正常狀態單子。這是三者中最簡單的。 (在一些老的教程,你可以看到使用State
構造,但這已經被替換爲state
功能,因爲State s
現在是StateT s Identity
一個類型別名。)
StateT
是爲State
單子的單子轉換。它增加了一層通用性,允許你在狀態中放置一個任意monad。這對簡單的解析器很有用,它可以使用例如StateT [Token] Maybe Result
將解析表示爲可能失敗的有狀態操作。
MonadState
將情況概括得更遠。有一個實例Monad m => MonadState s (StateT s m)
,但也有一些實例,如允許您在單粒變換器StateT
上執行有狀態操作的實例。所有基本狀態功能(get
,set
,modify
等)可與MonadState
的實例一起使用。
你確切的問題是什麼?你想要完成什麼類型的目標?你的困惑來自哪裏?你不知道'newtype','type'和'class'是什麼?如果你只是不理解這些結構,那麼只需閱讀一些Haskell教程。 StackOverflow是針對特定問題的。 – Shersh
問題是...? :) – Alec