为什么我们的函数需要采用状态和输入而不仅仅是包含输入的状态(或包含状态的输入?)。
我假设你可能想要使用相同的状态应用不同的输入,因此你想分开保存它们,但这是唯一的原因吗?
我感觉我错过了一些基本的东西,但我无法理解。
答案 0 :(得分:1)
这是因为方便。一般来说,单独的参数,如果它们在概念上分开(例如,它们不是单个对象的属性,例如),则优于打包在数据类型中,因为在前一种情况下,可以使用currying,combinators等功能方法的优点。
如果没有monad,每个有状态函数看起来都像foo :: b -> s -> (s, a)
,对于monad,我们可以提取公共部分,命名为:newtype State s a = State (s -> (s, a))
,并定义return
和{{1} } 为了它。此外,任何简单的函数>>=
都可以通过简单的结果更改轻松转换为有状态:bar :: a -> b
。如果输入和状态都在一个参数中进行(例如,元组:bar :: a -> State s b
,那就不可能。
答案 1 :(得分:1)
我不完全确定你的实际问题是什么,但这里有一些事实可能会回答:
状态数据是可变的(通过State
monad),输入数据是不可变的。在Haskell中,通常可以实现最大的类型级安全性。如果你将输入与状态联合起来,那么你也可以将它变为可变的。
Monads没有输入。您可能会考虑arrows。实际上有a state arrow。
答案 2 :(得分:0)
状态monad很有用,因为它强制执行从类型中显而易见的模式。
而不是让代码中的每个函数看起来像:
foo state x y = ... return (state', z)
您可以使用State
来明确您的意图。
答案 3 :(得分:0)
术语:如果你是Haskell的新手,很容易被“状态数据可变”等语句搞糊涂/欺骗。来自命令式程序的人可能会采用“可变”来表示更改现有位置的值。对于Haskell的某些部分(例如,IORef
)确实如此。在State
monad案例中,事实并非如此。
State
支持将状态变为新状态 - 新状态完全独立于旧状态。没有任何东西发生变异。
有时这被称为“有效”编程 - 你可以获得效果的好处,但不使用“真正的”副作用 - State
是完全纯粹的。