Если вы косоглазие, вы можете увидеть, что State
действительно является оберткой для функциональности, относящейся к функциям типа (a,s)->(b,s)
, только в карри: a -> s -> (b,s)
.
Цепные функции типа (a,s)->(b,s)
действительно просты - простая композиция. Таким образом, они могут пройти как «состояние» (s
), так и вычислительные «результаты» (a
для создания b
) по цепочке вызовов. Конечно, становится очевидным, что различие между «состоянием» и «результатами» произвольно. Но если вы имеете дело с карнидной версией, это становится немного более сложным, и об этом заботится >>=
.
Но что такое Monad
, если мы можем «цеплять очень легко» функции типа до каррирования?Monad
должен заботиться о шаблоном, связанном с распространением состояния, даже если функция не зависит от него, потому что большинство функций этого не делают. Они начинаются в зависимости от состояния и изменения состояния (ну, на самом деле, они становятся полностью работоспособными), когда они получают доступ ко второй проекции кортежа, используя get
и put
. Без State
монады, которая будет выглядеть так:
get :: (a,s) -> (s,s)
get (_,s) = (s,s)
put :: (s,s) -> ((),s)
put (s,_) = ((),s)
По выделки (a,s)->(b,s)
, мы получаем гигиенический с учетом состояния вычисления, отделяя проблемы для зависимости от a
и s
: мы избавляемся от явной зависимости от s
, если специально не обнаруживаемых с помощью использование get
и put
. Это важно иметь в виду их существование - в противном случае это не совсем очевидно, что возня с прохождением s
вокруг:
get = State $ \s -> (s,s)
put s = State $ \_ -> ((),s)
Теперь вернемся к >>=
. Что эта функция делает, объединяет s->(a,s)
и a->s->(b,s)
, чтобы получить s->(b,s)
- который теперь может использоваться для объединения с >>=
еще. Если бы мы не имели State
конструктора обертки, связывание будет выглядеть следующим образом:
as >>= f = \s -> (uncurry f) $ as s
То есть, учитывая состояние, корм в as
производить (a,s)
, которые подают в f
(uncurried, чтобы получить (a,s)->(b,s)
снова) в производят (b,s)
. Но так как мы имеем State
оболочку, она становится немного менее очевидно:
(State as) >>= f = State $ \s -> let (a,s') = as s --mean to call f (a,s'), but
(State g) = f a --need to remove the wrapper
in g s' --to pass s' to (s->(b,s))
разворачивания в вашем примере это делается с помощью runState
.
'>> =' является сердцем * монады *, поэтому ваш вопрос вроде сводится к * «что такое монады?» *. Поскольку объем этого вопроса немного велик, я предлагаю вам ознакомиться с введением, таким как [глава монады LYAH] (http://learnyouahaskell.com/a-fistful-of-monads). – gspr
@gspr Однако речь идет о конкретной монаде. Мне кажется, что спрашивать, как работает 'concatMap', спрашивает, как работают монады, потому что' concatMap = flip (>> =) '. –