я совершенно запутался между
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
позволяют составлять такие функции более удобным способом, делая неявным перетасовку кортежей для обработки вывода (a, s)
. С помощью нескольких основных операций, которые манипулируют состоянием...
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
, то он удовлетворяет две разные потребности. Во-первых, мы можем использовать механизм преобразования монад, чтобы иметь StateT s m
в качестве базовой монады для некоторого другого преобразователя в стеке преобразователей (произвольный пример: MaybeT (StateT Int IO)
). Однако в этом случае lift
из MonadTrans
становится необходимым использовать get
и put
. Один из способов прямого использования операций в таких случаях — через 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
Во-вторых, если мы хотим иметь монаду состояния с реализацией, отличной от реализации в transformers, мы можем сделать ее экземпляром MonadState
, чтобы мы сохраняли те же основные операции и, пока мы пишите сигнатуры типов в терминах MonadState
, чтобы при необходимости было проще менять реализации.
State
для вашей обычной монады состояния. Это самый простой из трех. (В некоторых старых учебниках вы можете увидеть использование конструктора State
, но он был заменен функцией state
, поскольку State s
теперь является псевдонимом типа для StateT s Identity
.)
StateT
является преобразователем монады для монады State
. Это добавляет уровень общности, позволяя вам поместить произвольную монаду в состояние. Это полезно для простых парсеров, которые могут использовать, например. StateT [Token] Maybe Result
, чтобы представить синтаксический анализ как операцию с отслеживанием состояния, которая может завершиться ошибкой.
MonadState
обобщает ситуацию еще дальше. Есть экземпляр Monad m => MonadState s (StateT s m)
, но есть и такие экземпляры, как тот, который позволяет вам выполнять операции с отслеживанием состояния над преобразователями монад StateT
. Все базовые функции состояния (get
, set
, modify
и т. д.) можно использовать с экземпляром MonadState
.
newtype
,type
иclass
? Если вы просто не понимаете эти структуры, просто прочитайте несколько руководств по Haskell. StackOverflow предназначен для конкретных вопросов. - person Shersh   schedule 16.04.2017