在一个项目中,我使用的模块包含我在项目其余部分使用的全局(常量初始化)。我选择将它们放入模块中以避免大量参数传递。问题是该模块必须在运行时使用程序执行的参数进行初始化。
如何在功能范例中完成,例如像Haskell这样的语言?
编辑:
更确切地说,我用命令式语言(Ada)编写项目代码,这就是为什么我可以使用包含在运行时初始化的变量的模块,然后用作全局常量(带内联的getter)。但是,对函数式编程感兴趣,我想知道如何在这个范例中获得相同的结果;我的意思是在其余的代码中使用光签名(使用全局常量),在内存的数据部分中定位模块数据,甚至能够分别初始化模块的不同“常量”等。
答案 0 :(得分:4)
如果程序的行为取决于命令行中使用的参数,则根本无法隐藏这一事实 - 它必须出现在程序组件的类型中。最简单的方法是编写
data Options = {- ... -}
doMyProgram :: Options -> IO ()
myModule'sConstantA :: Options -> A
myModule'sConstantB :: Options -> B
将Options
作为依赖于它的任何操作或值的参数。花哨的设计通常还为程序定义一个自定义monad M
,其中包含MonadReader Options M
实例以减少类型签名的大小。
答案 1 :(得分:0)
严格地说,它不是不可能,因为可能不应该。
import System.Environment
import System.IO.Unsafe
firstArg :: String
firstArg = head $ unsafePerformIO getArgs
{-# NOINLINE firstArg #-}
main = putStrLn firstArg
请注意六行代码中出现“不安全”一词的次数。
它很脏且很粗糙,但IMO,这个范例有一些有效的用例,而全局常量初始化就是其中之一。例如,我用它来加载游戏中的关卡文件。