Я что-то упустил из фундаментальной монады? Зачем хранить состояние и ввод отдельно?
Почему наши функции должны принимать состояние и вход, а не просто состояние, которое включает в себя вход (или вход, который включает в себя состояние?).
Я предполагаю, что вы, возможно, захотите применить разные входные данные с одним и тем же состоянием, и поэтому вы хотите хранить их отдельно, но это единственная причина?
Я чувствую, что упускаю что-то фундаментальное, но не могу этого понять.
4 ответа
Это связано с удобством. В целом, отдельные аргументы, если они концептуально разделены (например, они не являются свойствами одного объекта), лучше, чем упакованные в тип данных, потому что в первом случае вы можете использовать карринг, комбинаторы и другие Преимущества функционального подхода.
Без монад каждая функция с состоянием выглядела бы как foo :: b -> s -> (s, a)
и с помощью монад мы можем извлечь общую часть, назвать ее: newtype State s a = State (s -> (s, a))
и определить return
а также >>=
для этого. Более того, любая простая функция bar :: a -> b
можно легко превратить в состояние с помощью простого изменения результата: bar :: a -> State s b
, Это было бы невозможно, если бы и вход, и состояние передавались в одном аргументе (скажем, кортеж: foo :: (s, a) -> (s, a)
,
Я не совсем уверен, каков ваш настоящий вопрос, но вот некоторые факты, которые могли бы ответить на него:
Данные состояния изменчивы (через
State
монада), входные данные неизменны. В Хаскеле принято достигать максимальной безопасности на уровне типов. Если вы объединяете ввод с состоянием, вы также сделаете его изменяемым без какой-либо цели.Монады не имеют входов. Вы можете думать о стрелах. А на самом деле есть государственная стрела.
Государственная монада полезна, потому что она навязывает шаблон, который очевиден из типа.
Вместо того, чтобы каждая функция в вашем коде выглядела так:
foo state x y = ... return (state', z)
ты можешь использовать State
чтобы понять, каково ваше намерение.
Терминология: если вы новичок в Haskell, вас легко запутать / одурачить такими заявлениями, как "Состояние данных изменчиво". Кто-то из императивных программ может воспринимать "изменчивость" как означающее изменение значения в существующем местоположении. Для некоторых частей Haskell (например, IORef
) это действительно так. в State
в случае с монадой это не так.
State
поддерживает переход государства в НОВОЕ состояние - новое состояние полностью не зависит от старого. Ничего не мутировало на месте.
Иногда это называется "эффективным" программированием - вы получаете преимущества от эффектов, но без использования "настоящих" побочных эффектов - State
совершенно чисто.