【问题标题】:Module initialization in functional programing函数式编程中的模块初始化
【发布时间】:2016-02-21 14:17:58
【问题描述】:

在一个项目中,我使用了一个模块,其中包含我在项目的其余部分中使用的全局(初始化后为常量)内容。我选择将它们放入一个模块中以避免传递大量参数。问题是这个模块必须在运行时使用程序执行的参数进行初始化。

如何在函数范式中做到这一点,例如像 Haskell 这样的语言?

编辑:

更准确地说,我用命令式语言 (Ada) 编写我的项目,这就是为什么我可以使用包含在运行时初始化的变量的模块,然后用作全局常量(使用内联 getter)。但是,对函数式编程感兴趣,我想知道如何在这种范式中获得相同的结果;我的意思是在代码的其余部分(使用全局常量)中使用轻签名,将模块数据本地化在内存的数据部分,甚至能够分别初始化模块的不同“常量”,等等。

【问题讨论】:

  • 好吧,您可以使用getArgs 阅读main 中的参数并传递它们-如果您想花哨,可以使用Read/StateMonad(Transformers) 等-您当然不能做是在您的模块中使用常量值 - 对于更多内容,您必须更具体,因为这个问题确实很广泛
  • 一些函数式语言(但不是 Haskell)提供一流的模块,可以使用动态绑定进行初始化。
  • @Carsten 你说得对,我编辑了我的帖子以提出更具体的问题。
  • @dfeuer 你能举个例子吗,我很想看看这些语言。
  • @dfeuer 好的,我看看 OCaml,感谢让我发现了这个功能。

标签: haskell functional-programming


【解决方案1】:

如果您的程序的行为取决于命令行中使用的参数,那么根本无法隐藏这一事实——它必须出现在程序组件的类型中。最简单的方法是写

data Options = {- ... -}

doMyProgram :: Options -> IO ()
myModule'sConstantA :: Options -> A
myModule'sConstantB :: Options -> B

Options 作为参数提供给任何依赖它的操作或值。花哨的设计通常还为包含MonadReader Options M 实例的程序定义一个自定义monad M,以减少类型签名的大小。

【讨论】:

  • 感谢您的回答。正如您所说,没有办法使选项全局后期初始化常量? monad Reader 的问题是我不是很了解它,但是签名即使更长,因为它必须在返回的类型中。那么内存中数据的位置呢? (为了更准确,我编辑了我的帖子)
  • @olp 很抱歉,即使你用不同的词问同一个问题,答案也是一样的。
【解决方案2】:

严格来说,这并不是不可能,而是可能不应该这样做

import System.Environment
import System.IO.Unsafe

firstArg :: String
firstArg = head $ unsafePerformIO getArgs
{-# NOINLINE firstArg #-}

main = putStrLn firstArg

请注意“不安全”一词在这六行 sn-p 中出现了多少次。

它又脏又粗,但在 IMO 中,这种范式有一些有效的用例,全局常量初始化就是其中之一。例如,我用它在我的游戏中加载关卡文件。

【讨论】:

    猜你喜欢
    • 2018-08-29
    • 1970-01-01
    • 2011-07-02
    • 2015-11-05
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多