[英]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.cabal
和Setup.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
而攀登那座山对新手来说就像他们做错了一样。
在花了太多时间尝试每个排列之后,我在这里整理了很好的答案,还有许多其他来自其他地方的答案,对它们进行了测试,并总结了结果。 完整的文章在这里。
解决方案的相关摘要是:
cabal install --lib the-package
进行全局安装。stack exec --package containers --package optparse-generic [...and so on] -- runghc hello.hs
stack new my-project hraftery/minimal
,将您的代码放入Main.hs
并将您的依赖项放入my-project.cabal
(可能还有stack.yaml
- 查看文章),然后运行stack build
以自动提取并构建所有依赖项.-- stack --resolver lts-6.25 script --package the-package
添加到.hs
文件的顶部并设置其可执行位。对于我的编辑/测试/运行工作流程(例如,分别使用 VS Code、GHCi 和 GHC),我发现很清楚什么在实践中有效。 总之:
minimal
模板开始的 Stack 项目是向更复杂和更流行的方法的平稳过渡。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.