Haskell 标准:无法加载模块,隐藏包
Haskell Criterion: Could not load module, hidden package
当我完全按照 this Criterion tutorial 所说的开始操作时,出现错误。我究竟做错了什么?是教程错了吗?如果是这样,有什么地方可以让我学习正确使用 Criterion 的方法吗?
具体来说,正如教程所说,我 运行 在命令行中输入以下内容:
cabal update
cabal install -j --disable-tests criterion
这个运行没有错误。然后我把教程里的例子程序一模一样复制过来:
import Criterion.Main
-- The function we're benchmarking.
fib m | m < 0 = error "negative!"
| otherwise = go m
where
go 0 = 0
go 1 = 1
go n = go (n-1) + go (n-2)
-- Our benchmark harness.
main = defaultMain [
bgroup "fib" [ bench "1" $ whnf fib 1
, bench "5" $ whnf fib 5
, bench "9" $ whnf fib 9
, bench "11" $ whnf fib 11
]
]
我将其放入一个名为 benchTest.hs 的文件中,然后我使用命令行完全按照教程中的说明编译程序,但使用 benchTest 代替了他们所谓的 Fibber它。具体来说,我在命令行中运行如下:
ghc -O --make benchTest
这导致了这个错误:
benchTest.hs:1:1: error:
Could not load module `Criterion.Main'
It is a member of the hidden package `criterion-1.5.13.0'.
You can run `:set -package criterion' to expose it.
(Note: this unloads all the modules in the current scope.)
It is a member of the hidden package `criterion-1.5.13.0'.
You can run `:set -package criterion' to expose it.
(Note: this unloads all the modules in the current scope.)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
1 | import Criterion.Main
| ^^^^^^^^^^^^^^^^^^^^^
阴谋集团进化简史
纵观其历史,Cabal 经历了一次巨大的变革
有效,通常表示为 v1-
命令与 v2-
命令;例如
从 Cabal 2 开始,你可以说 cabal v1-install
或 cabal v2-install
。发生什么了
当你说 cabal install
取决于 Cabal 版本时:Cabal 2 将使用
默认情况下 v1-install
而 Cabal 3 将使用 v2-install
。的变化
默认值反映了首选的操作模式。如此一来,v1
就变成了
基本上没有维护。我不希望它很快被删除,因为有一个
一群顽固的旧方法支持者。但我个人认为,首先,
新方法(有趣的是你可以使用 cabal new-install
作为同义词)在技术上是
更好,其次,新手应该使用它,因为它更好
记录在案,您可以获得更多帮助(在许多情况下,
由于 above-mentioned 的优势,更容易提供帮助)
为什么 v1
被包含在 v2
中(简而言之)
运行 在 v1
中遇到的主要问题是不兼容的依赖项
几个项目。想象一下,您从事的项目 A
依赖于包 X
版本 42
,同时您从项目 B
开始
也取决于 X
但版本 43
。你猜怎么着:你不能 v1-build
同一台机器上的两个项目,而不会清除 cabal
之间的缓存。
这就是它在黑暗时代(从 2000 年代中期到每年
2010 年代)。
在那之后,cabal 沙箱 到来了。他们允许你建立我们想象中的
项目 A
和 B
不那么麻烦,但界面不是很好,而且更多
重要的是,每个沙盒都是独立的,因此包含了很大一部分
重复的二进制文件;例如A
和 B
也可能依赖于相同的 Y
版本 13
,所以理论上不需要构建和存储 Y
两次,
但这正是 cabal 沙箱会做的。
Cabal v2
于 2010 年代后期到来并带来了:
通过名为 environment files 和共享的(也是最近的)GHC 功能进行项目
通过 Cabal store 构建工件(这样你就不会存储同一事物的许多副本)。
环境和v2-install
您可以为
每个项目(A
、B
等)通过
cabal v2-install --lib X-42 --package-env=.
在各自项目的目录中。关于语法的几个注释:
v2-
在 Cabal 3 中可以省略,因为它是默认值;
只要install
正确,标志的顺序并不重要
在 cabal
之后;
--lib
很重要,因为默认情况下你只会得到可执行文件(那是
criterion
会发生什么:该包包含一个可执行文件);
--package-env=.
表示:在当前创建GHC环境文件
目录(因此 .
)。如果命令成功,您会注意到一个新的
(Linux 上的“隐藏”)文件在当前目录中,名称类似于
.ghc.environment.x86_64-linux-9.0.2
。这是告诉所有的文件
随后调用此目录中的 GHC 以在其中搜索 Cabal 编译的库
并存储在... Cabal store(在 Linux 上是 ~/.cabal/store
目录
默认)。原则上,您可以使用 .
以外的环境值,
如果该值不对应于路径,它将是一个命名的
环境。 More details in Cabal reference manual… 在实践中,我发现
99.99% 的案例由 --package-env=.
.
完美服务
X-42
表示版本42
的包X
应该添加到新的
创造的环境。你可以省略版本(你会得到“some compatible
version"), 你可以列出多个包。
如果没有指定环境,cabal v2-install --lib
是什么意思
表示default
环境。有一个名为
default
。它与 v1
有同样的问题(见上文)。所以,在
练习它可以工作,但它会非常脆弱,特别是如果你进入
上面描述的“project A
and project B
”情况。哪怕你只
现在处理一个项目,我建议使用 --package-env
因为它是未来的
证明。
为什么初始错误
如您所说,您使用的是 Cabal 2,因此 v1-install
最初看到
可怕的“隐藏包”错误——这是什么原因?老实说,我
不知道。而且我怀疑如果不回滚到那个旧版本就很容易计算出来
阴谋集团版本和更多实验。正如我上面所说, v1
并没有真正维护
不再,即使它看起来像 Cabal 中的一个错误(这完全有可能
特别是在 Cabal 2 系列的早期版本中),没有人可能会
打扰一下。
老教程不行了是不是很难过
是的。不幸的是,软件技术必须发展才能使世界成为
更好的地方live(再看上面v2
的原因)。有时候这个
开发必须打破向后兼容性。理想情况下,我们会去更新所有
反映变化的教育材料和手册,但这很难
可能的。叹。 Haskell 的新用户必须小心谨慎并尊重创意
到 v1
到 v2
的转变,并尝试尽早对 v2
有一个基本的了解
并尝试将它应用到仍然存在的优秀但古老的教程中。
环境是最好的方法吗?
v2
的一些设计者和支持者认为环境文件是
太微妙的功能。作为(“适当的”)替代方案,他们建议创建一个
full-fledged 您开始的每个项目的 cabal 包。这相当于打电话
cabal init
,这将在当前创建一个 <project-name>.cabal
文件
目录,并维护 .cabal
文件,包括包列表
那里的依赖;您还将使用 cabal v2-build
构建项目(而不是直接调用 GHC)。
虽然更强大,但毫不奇怪,这个想法不会沉睡
很多人使用 Haskell 来尝试很多独立的小东西:
每次都创建一个完整的“包”感觉很蹩脚。好吧,这只是一个额外的
在实践中归档,如果你将它与
environments-based 我上面描述的方法,它还维护了一个额外的
文件,但在那种情况下你永远不需要手动编辑它(不像
.cabal
文件)。总而言之,在“尝试一件小事”的场景中,我发现
environments-based 方法对我来说效果更好。但它确实有其
与 package-based 方法相比的局限性,特别是 hard to figure out
如何获取环境中依赖项的分析版本。但那是一个
改天的故事……
您可以在 Cabal issue 中找到有关如何改进 cabal v2-install --lib
的更多讨论。
如果您想遵循官方认可的做事方式(即通过包),请花一点时间阅读 the Getting Started section of the Cabal manual — 它非常清楚,并且准确地展示了一个简单应用程序的示例对外部包的依赖。
当我完全按照 this Criterion tutorial 所说的开始操作时,出现错误。我究竟做错了什么?是教程错了吗?如果是这样,有什么地方可以让我学习正确使用 Criterion 的方法吗?
具体来说,正如教程所说,我 运行 在命令行中输入以下内容:
cabal update
cabal install -j --disable-tests criterion
这个运行没有错误。然后我把教程里的例子程序一模一样复制过来:
import Criterion.Main
-- The function we're benchmarking.
fib m | m < 0 = error "negative!"
| otherwise = go m
where
go 0 = 0
go 1 = 1
go n = go (n-1) + go (n-2)
-- Our benchmark harness.
main = defaultMain [
bgroup "fib" [ bench "1" $ whnf fib 1
, bench "5" $ whnf fib 5
, bench "9" $ whnf fib 9
, bench "11" $ whnf fib 11
]
]
我将其放入一个名为 benchTest.hs 的文件中,然后我使用命令行完全按照教程中的说明编译程序,但使用 benchTest 代替了他们所谓的 Fibber它。具体来说,我在命令行中运行如下:
ghc -O --make benchTest
这导致了这个错误:
benchTest.hs:1:1: error:
Could not load module `Criterion.Main'
It is a member of the hidden package `criterion-1.5.13.0'.
You can run `:set -package criterion' to expose it.
(Note: this unloads all the modules in the current scope.)
It is a member of the hidden package `criterion-1.5.13.0'.
You can run `:set -package criterion' to expose it.
(Note: this unloads all the modules in the current scope.)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
1 | import Criterion.Main
| ^^^^^^^^^^^^^^^^^^^^^
阴谋集团进化简史
纵观其历史,Cabal 经历了一次巨大的变革
有效,通常表示为 v1-
命令与 v2-
命令;例如
从 Cabal 2 开始,你可以说 cabal v1-install
或 cabal v2-install
。发生什么了
当你说 cabal install
取决于 Cabal 版本时:Cabal 2 将使用
默认情况下 v1-install
而 Cabal 3 将使用 v2-install
。的变化
默认值反映了首选的操作模式。如此一来,v1
就变成了
基本上没有维护。我不希望它很快被删除,因为有一个
一群顽固的旧方法支持者。但我个人认为,首先,
新方法(有趣的是你可以使用 cabal new-install
作为同义词)在技术上是
更好,其次,新手应该使用它,因为它更好
记录在案,您可以获得更多帮助(在许多情况下,
由于 above-mentioned 的优势,更容易提供帮助)
为什么 v1
被包含在 v2
中(简而言之)
运行 在 v1
中遇到的主要问题是不兼容的依赖项
几个项目。想象一下,您从事的项目 A
依赖于包 X
版本 42
,同时您从项目 B
开始
也取决于 X
但版本 43
。你猜怎么着:你不能 v1-build
同一台机器上的两个项目,而不会清除 cabal
之间的缓存。
这就是它在黑暗时代(从 2000 年代中期到每年
2010 年代)。
在那之后,cabal 沙箱 到来了。他们允许你建立我们想象中的
项目 A
和 B
不那么麻烦,但界面不是很好,而且更多
重要的是,每个沙盒都是独立的,因此包含了很大一部分
重复的二进制文件;例如A
和 B
也可能依赖于相同的 Y
版本 13
,所以理论上不需要构建和存储 Y
两次,
但这正是 cabal 沙箱会做的。
Cabal v2
于 2010 年代后期到来并带来了:
通过名为 environment files 和共享的(也是最近的)GHC 功能进行项目
通过 Cabal store 构建工件(这样你就不会存储同一事物的许多副本)。
环境和v2-install
您可以为
每个项目(A
、B
等)通过
cabal v2-install --lib X-42 --package-env=.
在各自项目的目录中。关于语法的几个注释:
v2-
在 Cabal 3 中可以省略,因为它是默认值;只要
install
正确,标志的顺序并不重要 在cabal
之后;--lib
很重要,因为默认情况下你只会得到可执行文件(那是criterion
会发生什么:该包包含一个可执行文件);
完美服务--package-env=.
表示:在当前创建GHC环境文件 目录(因此.
)。如果命令成功,您会注意到一个新的 (Linux 上的“隐藏”)文件在当前目录中,名称类似于.ghc.environment.x86_64-linux-9.0.2
。这是告诉所有的文件 随后调用此目录中的 GHC 以在其中搜索 Cabal 编译的库 并存储在... Cabal store(在 Linux 上是~/.cabal/store
目录 默认)。原则上,您可以使用.
以外的环境值, 如果该值不对应于路径,它将是一个命名的 环境。 More details in Cabal reference manual… 在实践中,我发现 99.99% 的案例由--package-env=.
.X-42
表示版本42
的包X
应该添加到新的 创造的环境。你可以省略版本(你会得到“some compatible version"), 你可以列出多个包。
如果没有指定环境,cabal v2-install --lib
是什么意思
表示default
环境。有一个名为
default
。它与 v1
有同样的问题(见上文)。所以,在
练习它可以工作,但它会非常脆弱,特别是如果你进入
上面描述的“project A
and project B
”情况。哪怕你只
现在处理一个项目,我建议使用 --package-env
因为它是未来的
证明。
为什么初始错误
如您所说,您使用的是 Cabal 2,因此 v1-install
最初看到
可怕的“隐藏包”错误——这是什么原因?老实说,我
不知道。而且我怀疑如果不回滚到那个旧版本就很容易计算出来
阴谋集团版本和更多实验。正如我上面所说, v1
并没有真正维护
不再,即使它看起来像 Cabal 中的一个错误(这完全有可能
特别是在 Cabal 2 系列的早期版本中),没有人可能会
打扰一下。
老教程不行了是不是很难过
是的。不幸的是,软件技术必须发展才能使世界成为
更好的地方live(再看上面v2
的原因)。有时候这个
开发必须打破向后兼容性。理想情况下,我们会去更新所有
反映变化的教育材料和手册,但这很难
可能的。叹。 Haskell 的新用户必须小心谨慎并尊重创意
到 v1
到 v2
的转变,并尝试尽早对 v2
有一个基本的了解
并尝试将它应用到仍然存在的优秀但古老的教程中。
环境是最好的方法吗?
v2
的一些设计者和支持者认为环境文件是
太微妙的功能。作为(“适当的”)替代方案,他们建议创建一个
full-fledged 您开始的每个项目的 cabal 包。这相当于打电话
cabal init
,这将在当前创建一个 <project-name>.cabal
文件
目录,并维护 .cabal
文件,包括包列表
那里的依赖;您还将使用 cabal v2-build
构建项目(而不是直接调用 GHC)。
虽然更强大,但毫不奇怪,这个想法不会沉睡
很多人使用 Haskell 来尝试很多独立的小东西:
每次都创建一个完整的“包”感觉很蹩脚。好吧,这只是一个额外的
在实践中归档,如果你将它与
environments-based 我上面描述的方法,它还维护了一个额外的
文件,但在那种情况下你永远不需要手动编辑它(不像
.cabal
文件)。总而言之,在“尝试一件小事”的场景中,我发现
environments-based 方法对我来说效果更好。但它确实有其
与 package-based 方法相比的局限性,特别是 hard to figure out
如何获取环境中依赖项的分析版本。但那是一个
改天的故事……
您可以在 Cabal issue 中找到有关如何改进 cabal v2-install --lib
的更多讨论。
如果您想遵循官方认可的做事方式(即通过包),请花一点时间阅读 the Getting Started section of the Cabal manual — 它非常清楚,并且准确地展示了一个简单应用程序的示例对外部包的依赖。