通过monad访问配置参数?

8 monads haskell

引自这里:http://www.haskell.org/haskellwiki/Global_variables

如果你有一个全局环境,各种函数可以从中读取(例如,你可以从配置文件中初始化),那么你应该将它作为一个参数线程化到你的函数中(之后很可能会在你的函数中设置它).主要的'行动'.如果显式参数传递使你烦恼,那么你可以用Monad"隐藏"它.

现在我正在写一些需要访问配置参数的东西,我想知道是否有人可以指向我的教程或任何其他资源来描述monad如何用于此目的.对不起,如果这个问题很愚蠢,我只是开始研究monad.现在阅读Mike Vainer的教程.

Pau*_*son 5

基本的想法是你编写这样的代码:

main = do
   parameters <- readConfigurationParametersSomehow
   forever $ do
      myData <- readUserInput
      putStrLn $ bigComplicatedFunction myData parameters

bigComplicatedFunction d params = someFunction params x y z
   where x = function1 params d
         y = function2 params x d
         z = function3 params y
Run Code Online (Sandbox Code Playgroud)

您可以使用IO操作读取"main"函数中的参数,然后将这些参数作为额外参数传递给工作函数.

这种风格的问题在于必须将参数块传递给需要访问它的每个小函数.这是一件令人讨厌的事.您发现调用树中的某些函数有十个级别现在需要一些运行时参数,您必须将该运行时参数作为参数添加到其间的所有函数中.这被称为tramp数据.

monad"解决方案"是将运行时参数嵌入Reader Monad中,并使所有函数成为monadic动作.这摆脱了显式的tramp数据参数,但用monadic类型替换它,并且在这个monad实际上正在为你做数据流浪.

命令式世界用全局变量解决了这个问题.在Haskell中,您可以像这样做同样的事情:

parameters = unsafePerformIO readConfigurationParametersSomehow
Run Code Online (Sandbox Code Playgroud)

第一次使用"参数"时,"readConfigurationParametersSomehow"会被执行,从那时起它就像一个常量值,至少只要你的程序正在运行.这是unsafePerformIO为数不多的正义用途之一.

但是,如果您发现自己需要这样的解决方案,那么您真的需要考虑一下您的设计.很可能你没有考虑将你的功能降低到最低点; 如果某些以前的纯函数突然需要运行时参数,那么请查看原因并查看是否可以某种方式利用更高阶函数.例如:

  • 传递使用参数而不是参数本身构建的函数.
  • 底部的worker函数返回一个函数,结果传递给更高级别的基于参数的函数.
  • 重构您的调用堆栈,以便基本操作由底部的低级基元完成,这些基元在顶部以依赖于参数的方式组成.

无论哪种方式都将涉及