【问题标题】:Access the configuration parameters through a monad?通过 monad 访问配置参数?
【发布时间】:2011-05-21 10:19:20
【问题描述】:

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

如果你有一个全局环境, 从中读取的各种功能(和 例如,您可能会初始化 从配置文件)然后你 应该将其作为参数线程 你的功能(在拥有之后,非常 可能,将其设置在您的“主要”中 行动)。如果显式参数 路过让你烦恼,那么你可以 用 Monad '隐藏'它。

现在我正在写一些需要访问配置参数的东西,我想知道是否有人可以向我指出一个教程或任何其他描述如何将 monad 用于此目的的资源。抱歉,如果这个问题很愚蠢,我才刚刚开始摸索单子。立即阅读 Mike Vainer 的教程。

【问题讨论】:

  • 为了让你开始,你正在寻找 reader monad。但是首先需要一些 IO 来获取环境。

标签: haskell monads


【解决方案1】:

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

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

您使用 IO 操作读取“main”函数中的参数,然后将这些参数作为额外参数传递给您的工作函数。

这种风格的问题是必须将参数块传递给需要访问它的每个小函数。这是一个麻烦。您发现调用树中向下十级的某些函数现在需要一些运行时参数,并且您必须将该运行时参数作为参数添加到其间的所有函数中。这被称为tramp data

monad 的“解决方案”是将运行时参数嵌入到Reader Monad 中,并将您的所有函数变成 monadic 动作。这摆脱了显式的 tramp data 参数,而是将其替换为 monadic 类型,并且在幕后,这个 monad 实际上正在为您执行数据迁移。

命令式世界通过一个全局变量来解决这个问题。在 Haskell 中,你可以做同样的事情:

parameters = unsafePerformIO readConfigurationParametersSomehow

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

但是,如果您发现自己需要这样的解决方案,那么您确实需要考虑您的设计。很可能您没有足够认真地考虑将您的功能向下推广;如果某些以前的纯函数突然需要运行时参数,请查看原因,看看您是否可以以某种方式利用高阶函数。例如:

  • 传递使用参数而不是参数本身构建的函数。
  • 让底部的工作函数返回一个函数作为结果,得到 向上传递以与更高级别的基于参数的函数组合。
  • 重构您的调用堆栈,以便基本操作由较低级别完成 底部的基元,它们在顶部以参数相关的方式组成。

无论哪种方式都会涉及

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多