繁体   English   中英

编译带有外部依赖项的 haskell 脚本,无需 cabal

[英]Compiling a haskell script with external dependencies without cabal

我对 Haskell 比较陌生,我意识到我可能会在这里与 stream 对抗,但尽管如此,我会问:

假设我有一个简短的 Haskell 脚本:

import Data.List.Split (splitOn)

main :: IO ()
main = do
  let orders = splitOn "x" "axbxc"
  putStrLn $ head orders

如果我只使用标准函数,我可以用ghc <script.hs>编译它。 因为我依赖split来提供splitOn function,所以编译失败。

现在,我可以毫无困难地使用project.cabalSetup.hs文件设置一个 cabal 项目,以便实际编译。 但是,对于独立脚本来说,这感觉像是很多额外的样板。

那么,有没有办法针对某些外部 package 编译 single.hs 文件? Something similar to what in Python would be done by pip install something , "installing the package into the interpreter", ie is there a way to install extra packages "into ghc", so that I for instance only need to provide some extra linking flag到ghc?

如果您使用Stack ,最简单的方法是编写“堆栈脚本”,这是一个 Haskell 文件,第一行中包含所需包的描述(实际上是调用stack指定适当的命令行参数)。 一个例子(从docs稍微修改):

$ cat turtle-example.hs
-- stack --resolver lts-6.25 script --package turtle
{-# LANGUAGE OverloadedStrings #-}
import Turtle
main = echo "Hello World!"
$ stack ./turtle-example.hs
Completed 5 action(s).
Hello World!
$ stack ./turtle-example.hs
Hello World!

此脚本使用turtle package; 运行时,Stack 下载并构建此依赖项,然后在脚本中可用。 (注意第二次运行时, turtle已经构建好了,不需要再重新构建了。)

碰巧的是,Stack 中的--package命令不仅限于脚本。 它也可以与其他 Stack 命令一起使用,例如,要编译您的程序,您应该能够运行stack ghc --resolver lts-16.27 --package split -- -ghc-options your-program-name.hs . 并且stack ghci --package split会给你一个 GHCi 提示,你可以在其中import Data.List.Split

(注意:这个答案侧重于 Stack 而不是 Cabal,只是因为我不太了解 Cabal。但是,我相信这一切也可以使用 Cabal 来完成。例如,我知道 Cabal 有一些非常相似的东西我上面提到的堆栈脚本,虽然我现在不记得语法了。)

编辑:有关如何使用 Cabal 执行此操作,请参阅@duplode 的答案

布拉德恩的回答中,与 Stack 脚本等效的阴谋集团将是:

#!/usr/bin/env cabal
{- cabal:
build-depends: base
            , split
-}

import Data.List.Split (splitOn)

main :: IO ()
main = do
  let orders = splitOn "x" "axbxc"
  putStrLn $ head orders

该脚本可以使用cabal run ,也可以直接通过授予它执行权限来运行。 如果需要,可以像往常一样将版本限制添加到脚本顶部的build-depends中。

(请注意,如果没有 Cabal,这实际上并不是一个解决方案,因为单独使用 GHC 这样做,即使可能,也不值得麻烦。无论如何,它肯定避免了需要多个文件的样板。)

您可以通过执行cabal install --lib split为当前用户安装到默认环境中。 package 应该随后可用于 ghc 和 ghci,而无需任何特殊选项。

更多信息在 Cabal 手册本节的底部。 它使用的v2命令现在是默认的,所以如果你有一个相当新的阴谋集团,你可以只使用install而不是v2-install

我认为这是 Haskell 中 package 管理战的典型切入点。 不是没有足够的建议,而是有很多建议,每一个都有自己的警告和假设。 为了splitOn而攀登那座山对新手来说就像他们做错了一样。

在花了太多时间尝试每个排列之后,我在这里整理了很好的答案,还有许多其他来自其他地方的答案,对它们进行了测试,并总结了结果。 完整的文章在这里

解决方案的相关摘要是:

  1. 全局安装
    • 您仍然可以使用cabal install --lib the-package进行全局安装。
  2. 使用 Stack 作为运行命令
    • 你可以直接使用stack,例如: stack exec --package containers --package optparse-generic [...and so on] -- runghc hello.hs
  3. 创建堆栈项目
    • 真正的交易。 运行stack new my-project hraftery/minimal ,将您的代码放入Main.hs并将您的依赖项放入my-project.cabal (可能还有stack.yaml - 查看文章),然后运行stack build以自动提取并构建所有依赖项.
  4. 使用堆栈脚本
    • 使您的 Haskell 文件本身成为可执行的堆栈脚本。 -- stack --resolver lts-6.25 script --package the-package添加到.hs文件的顶部并设置其可执行位。

对于我的编辑/测试/运行工作流程(例如,分别使用 VS Code、GHCi 和 GHC),我发现很清楚什么在实践中有效。 总之:

  1. 在一片沮丧的合唱中,全球安装非常适合我对您的用例的了解。
  2. 在全局安装没有意义的地方(例如,用于管理依赖版本或可移植),从我minimal模板开始的 Stack 项目是向更复杂和更流行的方法的平稳过渡。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM