我经常需要制作一个在某些地方以某种方式可配置使用的核心功能 - 即,它可以使用算法A或算法B,具体取决于命令行开关; 如果以某种方式设置'debug'标志,或者让它向stdout输出额外的详细信息.
我该如何实现这样的全局标志?
我看到4个选项,所有选项都不是很好.
从函数中读取命令行参数 - 坏,因为需要IO monad并且核心计算函数都是纯的,我不想在那里得到IO;
将一个参数从main/IO一直传递到需要改变行为的'leaf'函数 - 完全不可用,因为这意味着改变不同模块中的十几个不相关的函数来传递这个参数,我想试试这样的配置选项多次,而不是每次都更改包装代码;
使用unsafePerformIO得到一个真正的全局变量-感觉丑陋和矫枉过正这样一个简单的问题;
在函数中间右侧有两个选项的代码,并将其中一个注释掉.或者使用do_stuff_A和do_stuff_B函数,并根据全局函数的含义更改调用哪一个函数needDebugInfo=True.这就是我现在正在做的事情debuginfo,但它无法通过重新编译来改变,它不应该是最好的方式......
我不需要或想要全局可变状态 - 我希望有一个简单的全局标志,它在运行时是不可变的,但可以在程序启动时以某种方式设置.有什么选择吗?
根据介绍ReaderT,我只能找到:
ReaderT Env IO String
Run Code Online (Sandbox Code Playgroud)
这意味着
...is a computation which involves reading values from some environment
of type Env (the semantics of Reader, the base monad) and performing some
IO in order to give a value of type String.
Run Code Online (Sandbox Code Playgroud)
因此执行的顺序将成为
1. ( Already has ) some environment values -- ReaderT Env
2. Do `IO` accroding to these pre-existing values -- IO a
3. Use the `IO a` values to do more computations -- IO b...z
Run Code Online (Sandbox Code Playgroud)
这将要求我们的程序有一些预先存在的值作为环境,但我认为大多数程序需要加载这些环境值.如数据库URL,调试切换器或其他任何东西. …