2

为什么我们的函数需要接受状态和输入,而不仅仅是包含输入的状态(或包含状态的输入?)。

我假设您可能希望应用具有相同状态的不同输入,因此您希望将它们分开保存,但这是唯一的原因吗?

觉得我错过了一些基本的东西,但我无法掌握它。

4

4 回答 4

1

那是因为方便。一般来说,单独的参数,如果它们在概念上是分开的(我的意思是,它们不是单个对象的属性,例如),比打包在数据类型中要好,因为在前一种情况下,您可以使用柯里化、组合器和其他函数式方法的优点。

没有 monad,每个有状态的函数看起来像foo :: b -> s -> (s, a),而有了 monad,我们可以提取公共部分,将其命名为: newtype State s a = State (s -> (s, a)),并为它定义return>>=。此外,任何简单的函数bar :: a -> b都可以通过简单的结果更改轻松转换为有状态的:bar :: a -> State s b. 如果输入和状态都包含在单个参数中(例如,元组:foo :: (s, a) -> (s, a).

于 2014-02-26T07:02:32.800 回答
1

我不完全确定您的实际问题是什么,但这里有一些可能可以回答的事实:

  1. 状态数据是可变的(通过Statemonad),输入数据是不可变的。在 Haskell 中,实现最大的类型安全是常规的。如果您将输入与状态结合起来,您也会无缘无故地使其可变。

  2. 单子没有输入。您可能正在考虑箭头。而事实上还有一个状态箭头

于 2014-02-26T07:33:26.230 回答
0

State monad 很有用,因为它强制执行从类型中显而易见的模式。

而不是让代码中的每个函数看起来像:

foo state x y = ... return (state', z)

你可以用State它来明确你的意图是什么。

于 2014-02-26T07:39:41.283 回答
0

术语:如果您是 Haskell 的新手,很容易被“状态数据是可变的”之类的语句混淆/愚弄。来自命令式程序的人可能会认为“可变”意味着更改现有位置的值。对于 Haskell 的某些部分(例如IORef),这确实是正确的。在State单子的情况下,这是不正确的。

State支持将状态突变为新状态 - 新状态完全独立于旧状态。没有任何东西在原地发生变异。

有时这被称为“有效的”编程——你得到了效果的好处,但没有使用“真正的”副作用——State是完全纯粹的。

于 2014-02-26T16:13:24.923 回答