通过 monad 访问配置参数?
引用自此处: http://www.haskell.org/haskellwiki/Global_variables
如果你有一个全球环境, 各种函数从中读取(和 例如,您可以初始化 来自配置文件)然后你 应该将其作为参数传递给 你的功能(在拥有之后,非常 可能,将其设置在您的“主”中 行动)。如果显式参数 路过让你烦恼,那么你可以 用 Monad“隐藏”它。
现在我正在写一些需要访问配置参数的东西,我想知道是否有人可以向我指出一个教程或任何其他资源来描述如何将 monad 用于此目的。抱歉,如果这个问题很愚蠢,我才刚刚开始理解单子。现在阅读 Mike Vainer 关于它们的教程。
Quote from here: http://www.haskell.org/haskellwiki/Global_variables
If you have a global environment,
which various functions read from (and
you might, for example, initialise
from a configuration file) then you
should thread that as a parameter to
your functions (after having, very
likely, set it up in your 'main'
action). If the explicit parameter
passing annoys you, then you can
'hide' it with a Monad.
Now I'm writing something that needs access to configuration parameters and I wonder if someone could point me to a tutorial or any other resource that describes how monads can be used for this purpose. Sorry if this question is stupid, I'm just starting to grok monads. Reading Mike Vainer's tutorial on them now.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
基本思想是编写如下代码:
使用 IO 操作读取“main”函数中的参数,然后将这些参数作为额外参数传递给工作函数。
这种风格的问题在于,参数块必须传递给每个需要访问它的小函数。这很麻烦。您发现调用树中向下十层的某些函数现在需要一些运行时参数,并且您必须将该运行时参数作为参数添加到中间的所有函数。这称为流浪者数据。
monad“解决方案”是将运行时参数嵌入到 Reader Monad,并将所有功能都变成一元操作。这摆脱了显式的tramp data参数,而是用monadic类型替换它,并且在幕后这个monad实际上正在为您执行数据tramping。
命令式世界通过全局变量解决了这个问题。在 Haskell 中,你可以做同样的事情,如下所示:
第一次使用“参数”时,“readConfigurationParametersSomehow”被执行,从那时起,它的行为就像一个常量值,至少只要你的程序正在运行。这是 unsafePerformIO 为数不多的正当用途之一。
然而,如果您发现自己需要这样的解决方案,那么您确实需要考虑一下您的设计。很可能你没有认真思考如何将你的职能推广到更底层;如果某个以前的纯函数突然需要运行时参数,那么请查看原因并看看是否可以以某种方式利用高阶函数。例如:
传递到更高级别的基于参数的函数组成。
底部的原语在顶部以参数相关的方式组成。
无论哪种方式都会涉及
The basic idea is that you write code like this:
You read the parameters in the "main" function with an IO action, and then pass those parameters to your worker function(s) as an extra argument.
The trouble with this style is that the parameter block has to be passed down to every little function that needs to access it. This is a nuisance. You find that some function ten levels down in the call tree now needs some run-time parameter, and you have to add that run-time parameter as an argument to all the functions in between. This is known as tramp data.
The monad "solution" is to embed the run-time parameter in the Reader Monad, and make all your functions into monadic actions. This gets rid of the explicit tramp data parameter, but replaces it with a monadic type, and under the hood this monad is actually doing the data tramping for you.
The imperative world solves this problem with a global variable. In Haskell you can sort-of do the same thing like this:
The first time you use "parameters" the "readConfigurationParametersSomehow" gets executed, and from then on it behaves like a constant value, at least as long as your program is running. This is one of the few righteous uses for unsafePerformIO.
However if you find yourself needing such a solution then you really need to have a think about your design. Odds are you are not thinking hard enough about generalising your functions lower down; if some previously pure function suddenly needs a run-time parameter then look at the reason and see if you can exploit higher order functions in some way. For instance:
passed up to be composed with a parameter-based function at the higher level.
primitives at the bottom which are composed in a parameter-dependent way at the top.
Either way is going to involve