Путаница с StateT, State и MonadState

я совершенно запутался между

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

person hgiesel    schedule 16.04.2017    source источник
comment
Каков ваш точный вопрос? Каких целей вы пытаетесь достичь? Откуда ваше замешательство? Вы не знаете, что такое newtype, type и class? Если вы просто не понимаете эти структуры, просто прочитайте несколько руководств по Haskell. StackOverflow предназначен для конкретных вопросов.   -  person Shersh    schedule 16.04.2017
comment
А вопрос...? :)   -  person Alec    schedule 16.04.2017


Ответы (2)


Жил-был тип 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, чтобы при необходимости было проще менять реализации.

person duplode    schedule 16.04.2017

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.

person zbw    schedule 16.04.2017