在没有 cabal 的情况下编译具有外部依赖项的 haskell 脚本

问题描述

我对 Haskell 比较陌生,我意识到我可能会在这里逆流而上,但尽管如此,我还是会问:

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

import Data.List.Split (splitOn)

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

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

现在,我可以轻松地使用 project.cabalSetup.hs 文件设置 cabal 项目,以便实际编译。然而,对于独立脚本来说,这感觉就像是很多额外的样板。

那么,有没有办法针对某个外部包编译单个 .hs 文件 类似于 Python 中通过 pip install something 完成的操作,“将包安装到解释器”,即有没有办法将额外的包安装到“ghc”中,例如,我只需要向 ghc 提供一些额外的链接标志?

解决方法

如果你使用Stack,最简单的方法是写一个'Stack script',它是一个Haskell文件,第一行描述了所需的包(实际上是调用{{ 1}} 指定适当的命令行参数)。一个例子(从 the docs 稍微修改):

stack

此脚本使用 $ 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! 包;运行时,Stack 下载并构建此依赖项,此后它在脚本中可用。 (请注意,第二次运行时,turtle 已经构建完毕,因此无需再次重新构建。)

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

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

编辑:有关如何使用 Cabal 执行此操作的信息,请参阅 @duplode’s answer

,

bradrn's answer 中的 Stack 脚本等效的 Cabal 将是:

#!/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 安装到当前用户的默认环境中。然后,该软件包应该可用于 ghc 和 ghci,而无需任何特殊选项。

更多信息位于 this section in the Cabal manual 的底部。它使用的 v2 命令现在是默认的,所以如果你有一个相当新的阴谋集团,你可以只使用 install 而不是 v2-install