什么是RWS Monad以及何时使用

时间:2013-09-20 05:45:56

标签: haskell monad-transformers

我在mtl库中查找某些内容时遇到了RWS Monad及其MonadTransformer。那里没有真正的文档,我想知道这是什么以及它在哪里使用。

我已经发现RWS是Reader,Writer,State的缩写,那就是这三个monad变换器的堆栈。我无法弄清楚为什么这比国家本身更好。

2 个答案:

答案 0 :(得分:30)

最实际的原因是可测试性和更精确的类型签名。

haskell的关键优势在于你可以通过类型系统指定函数的功能。比较c#/ java类型:

public int CSharpFunction(int param) { ...

有一个haskell:

someFunction :: Int -> Int

haskell不仅告诉我们参数和返回类型所需的类型,还告诉我们函数可能会影响的类型。例如,它不能执行任何IO,也不能读取或更改任何全局状态,也不能访问任何静态配置数据。 c#函数可能都不是,但我们无法分辨。

这对测试有很大帮助。我们知道,我们需要使用haskell someFunction测试的唯一内容是它是否获得某些样本输入的预期输出。不需要任何可能的设置,并且该功能永远不会为相同的输入提供不同的结果。这使得纯函数的测试非常简单。


然而,通常一个功能不能是纯粹的。例如,它可能需要访问一些仅供阅读的全局信息。我们可以在函数中添加另一个参数:

readerFunc :: GlobalConfig -> Int -> Int

但是使用monad通常更容易,因为它们更容易构成:

readerFunc2 :: Int -> Reader GlobalConfig Int

测试这几乎就像测试纯函数一样简单。我们只需要测试输入Int值的各种排列,以及GlobalConfig阅读器配置值。

函数可能需要写出值(例如,用于记录)。这也可以使用monad来完成:

writerFunc :: Int -> Writer String Int

再次测试它几乎和纯函数一样简单。我们只是测试对于给定的Int输入,是否返回了相应的Int,以及正确的最终作者String

另一个功能可能需要读取和更改状态:

stateFunc :: Int -> State GlobalState Int

虽然这很难测试。我们不仅需要使用各种输入Ints和初始GlobalStates来检查输出,而且我们还需要测试最终的GlobalState是否是正确的值。


现在考虑一个函数:

  • 需要从ProgramConfig数据类型中读取
  • 将值写入字符串以进行记录
  • 使用和修改ProgramState值。

我们可以这样做:

data ProgramData = ProgramData { pState :: ProgramState, pConfig :: ProgramConfig, pLogs :: String }
complexFunction :: Int -> State ProgramData Int

但是,这种类型不是很准确。这意味着ProgramConfig可能会被更改,但它不会。它还暗示该函数可能使用pLogs值,而不是。此外,测试它更复杂,理论上,该函数可能会意外地更改程序配置,或在其计算中使用当前的pLogs值。

这可以通过以下方式得到很大改善:

betterFunction :: Int -> RWS ProgramConfig String ProgramState Int

这种类型非常准确。我们知道ProgramConfig只能从中读取。我们知道String只会改变。正如预期的那样,唯一需要读写的部分是ProgramState。这更容易测试,因为我们只需要测试ProgramConfig,ProgramState和Int的不同组合以进行输入,并检查输出IntStringProgramState的输出。我们知道我们不能无意中更改程序配置,或在计算中使用当前程序日志值。


haskell类型系统可以帮助我们,我们应该尽可能多地提供信息,以便它可以在我们做之前发现错误。

(请注意,此答案中的每个haskell类型可能等同于顶部的c#类型,具体取决于c#函数的实际实现方式。)

答案 1 :(得分:3)

国家是一个非常概括的概念,因此可用于许多事情。读者和作者可以被认为是一种具有某些约束的特殊形式的国家,你只能从读者那里读取而你只能写作者。使用这些特殊形式的状态,您可以更明确地明确关于您要实现的目标或意图究竟是什么。

另一个类比可能是使用地图/字典来建模任何东西(对象,数据,事件处理程序等),但使用更专业的地图/字典形式可以使事情更加明确