【问题标题】:How to import rather than load modules on startup with 'stack ghci'?如何使用“stack ghci”在启动时导入而不是加载模块?
【发布时间】:2017-04-16 12:57:26
【问题描述】:

我有一个名为prime-tools 的haskell 包。当我在包目录中使用stack ghci 时,我希望它会打开一个交互式ghci 并自动打开import prime-tools。相反,我发现它加载了 .cabal 文件中声明的所有模块

例如,这是我的 .cabal 文件的摘录,显示了声明了哪些模块:

library
  -- Modules exported by the library.
  exposed-modules:     PrimeTools.MathStuff, PrimeTools.Factors, PrimeTools.PQTrials, PrimeTools.Main, PrimeTools.Base, PrimeTools.Lucas

  -- Modules included in this library but not exported.
  other-modules:       PrimeTools.Extras

这就是我在项目文件夹中运行stack ghci 后收到ghci> 提示时发生的情况:

Ok, modules loaded: PrimeTools.MathStuff, PrimeTools.Factors, PrimeTools.PQTrials, PrimeTools.Main, PrimeTools.Base, PrimeTools.Lucas, PrimeTools.Extras.
ghci> 

加载模块而不是import prime-tools的问题是我现在可以使用所有模块中定义的所有函数无论它们是否被导出

由这种区别引起的问题的一个示例:包prime-tools 中有两个模块,它们实现了一个名为pfactor 的函数。其中一个是导出的,旨在供软件包的最终用户使用,而另一个仅供内部使用,不导出。

在有人 cmets 之前,有充分的理由有两个实现 pfactor,但这与我的问题无关。


我的问题:如何使用stack 自动启动具有本地版本ghcghci 环境并导入 我在其中运行命令的文件夹的包?

我想要的行为相当于运行以下命令序列:

stack ghci
ghci> :module -PrimeTools.MathStuff
ghci> :module -PrimeTools.Factors
ghci> :module -PrimeTools.PQTrials
ghci> :module -PrimeTools.Main
ghci> :module -PrimeTools.Base
ghci> :module -PrimeTools.Lucas
ghci> :module -PrimeTools.Extras
ghci> import PrimeTools.MathStuff
ghci> import PrimeTools.Factors
ghci> import PrimeTools.PQTrials
ghci> import PrimeTools.Main
ghci> import PrimeTools.Base
ghci> import PrimeTools.Lucas

这里的关键是我要导入在.cabal 文件中声明的exposed-modules,并且不要加载任何模块。不过,我不介意 other-modules 是否也被导入。有没有办法我可以使用stack 来做到这一点,而不必每次都运行这么长的命令序列?

【问题讨论】:

    标签: haskell ghci haskell-stack


    【解决方案1】:

    一个合理的解决方法是定义a custom GHCi macro 以按照您想要的方式导入您的模块。在您的项目根目录中创建一个.ghci 文件,如下所示:

    :{
    :def deload (\_ -> return 
        ":module -PrimeTools.MathStuff\n\
        \import PrimeTools.MathStuff"
        )
    :}
    

    这样,GHCi 中的:deload 命令将从范围中删除,然后重新导入PrimeTools.MathStuff——您可以将任意数量的模块添加到列表中。虽然我是使用 multiline string syntax 编写的,但您可以在括号内使用任何 String -> IO String 表达式,因此您可以随意拼写或扩展它。

    【讨论】:

    • 使用:load PrimeTools.Base 会引入未导出的定义。这一直是我的经验,过去曾将:load 与其他几个模块一起使用。
    • 您提供的链接是这样说的:“:load Main.hs ... 我们刚刚加载的 Main 模块顶层范围内的所有内容也在提示符范围内”,和 Myridium 一样,这确实也是我的经验。
    • 另外,当我运行stack ghci --no-load 时,我无法导入包。有人告诉我它是隐藏的:It is a member of the hidden package ‘prime-tools-0.1.2.0@prime_EA4ezNOr21Z4zu3ZQR52et’.
    • @jlmg 和 Myridium -- 似乎我在这种情况下混淆了* 的多种用途和含义;我已经删除了最后一段,直到我弄清楚如何更好地表达它。请注意,我写的部分原因是,尽管存在其他问题,但您确实希望加载模块,否则将找不到它们,从而导致 Myridium 在其他评论中描述的问题。
    • @Myridium 由于命令定义是任意的 Haskell,原则上应该可以解析 .cabal 文件并提取模块名称,即使使用 Cabal 库也可以这样做(参见 this question ) 只要在.ghci 文件的开头导入它。 (我只说“原则上”,因为我还没有尝试过。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多