我试图从MiranLipovača的书Learn You a Haskell中学习Haskell。本书和haskell.org都建议安装Haskell Platform,但我没有下载Manjaro Linux(基于Arch)。
我从2014年开始发现这个guide并决定从Manjaro的存储库安装这些软件包。这很好用,直到我想在Emacs中使用haskell-mode。我对此进行了故障排除,发现这是包的问题(主要是Stack)。
寻找解决方法,我发现了这个Reddit线程,它描述了安装Haskell(不是平台)的方法,以及包的问题。我按照其中一条评论进行了操作,最后使用描述here的脚本安装了Stack(和GHC):
wget -qO- https://get.haskellstack.org/ | sh
stack setup
stack update
我的问题与此有关:
$HOME/.stack/programs/x86_64-linux/ghc-tinfo6-nopie-8.2.2/lib/ghc-8.2.2
其中许多似乎已经安装。答案 0 :(得分:25)
这是一个(长期)替代答案。请注意,我曾经为初学者推荐Stack,但我改变了主意。
TL; DR:无论是Haskell平台还是纯粹的Stack安装都可以为您提供所需的一切,而且您不会错过"通过选择其中一个来做任何事情。您可能会发现使用" Generic"跳过Stack并安装Haskell平台最容易。 Linux安装程序,因为它带有您需要的所有内容,设置将更加符合LYAH书中描述的内容。当您在多个项目上进行更严肃的开发时,可以稍后安装Stack。如果您更喜欢坚持使用纯粹的Stack安装,我建议您只使用"全球项目"流程。无论哪种方式,你都可以使用" haskell-mode"以及下面建议的一些配置修复(包括如果您在仅限堆栈的安装的全局项目中工作将需要的密钥设置)。
这是一个很长的答案......
LYAH书预先列出了Stack,这肯定是它没有提到它的主要原因。在haskell.org,他们建议使用最小安装程序,Stack或Haskell平台。在2018年,所有这三种方法都是完全合理的方法来建立一个有效的Haskell环境。他们选择将不同版本的编译器和/或库隔离到沙盒中的方式各不相同。对于开发工作,以及他们最初安装的程度,但没有什么"缺少"来自其中任何一个无法按需安装的产品。根据您的选择,您的工作流程会有一些差异(见下文)。
Stack和Cabal都是组合包管理器和构建工具。 (Stack具有实际引导整个Haskell安装的附加功能,这就是为什么它本身也是一种安装方法。)当你通过LYAH工作时,你实际上并不是使用"构建工具"功能直接在您自己的项目上。 (GHC的内置构建工具足以构建小型,多模块项目。)您只需要包管理器功能即可安装其他库。
由于Stack和Cabal分别管理他们的包,如果你正在使用Stack,你将不需要直接使用Cabal。你可以根据需要安装它(实际上,Stack使用Cabal来实现一些深奥的功能,例如"堆栈解算器",并且需要在这些情况下安装它):
$ stack install cabal-install
但是,即使这会使" cabal"进入" $ HOME / .local / bin" (并且你想确保这是在你的道路上),你会发现你需要跳过篮球来运行它:
$ stack exec --no-ghc-package-path cabal -- list
就Stack环境而言,它并没有真正做任何有用的事情。
更新:关于" $ HOME / .local / bin"的说明路径。如果没有现有安装,则https://get.haskellstack.org/的安装脚本默认情况下可能会将堆栈本身安装到/usr/local/bin/stack
。但是,它应显示警告以将$HOME/.local/bin
放入您的路径中。如果将来使用stack upgrade
升级Stack,它将在那里安装新版本的stack
,如果您安装包含二进制文件的软件包,也将使用该目录。例如,stack install hlint
会将Haskell Lint程序hlint
安装到该目录。因此,在/usr/local/bin
之前将它放在您的路径和某个地方是一个好主意。
我认为这涵盖了前三个问题。对于你的最后一点,你安装Stack而不是Haskell平台的主要原因是,根据设计,Stack并没有真正安装除了" stack"之外的任何其他东西。本身。因此,所有Haskell工作包括运行Haskell解释器(" ghci")或编译器(" ghc")都需要在Stack环境中完成,或者使用特定的相应Stack命令:
$ echo 'main = putStrLn "Hello, world!"' > Hello.hs
$ stack ghc -- Hello.hs
[1 of 1] Compiling Main ( Hello.hs, Hello.o )
Linking Hello ...
$ ./Hello
Hello, world!
$
或者使用" stack exec"在适当的Stack环境中运行通用程序。例如,在堆栈下运行Bash shell有时会很有帮助,之后事情就像全局安装的Haskell Platform环境一样:
$ stack exec bash
$ ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
Prelude> :quit
$ ghc -O2 Hello.hs
[1 of 1] Compiling Main ( Hello.hs, Hello.o ) [flags changed]
Linking Hello ...
$ exit
$ ghc
The program 'ghc' is currently not installed. ...
$
你还缺少的另一件事是默认情况下Haskell平台会安装一大堆公共库,而在运行stack setup
之前,新的Stack环境几乎什么都没有(甚至不是编译器) )。在通过LYAH工作时,您可能会发现需要定期安装其他库。例如,在输入和输出章节中,使用随机数(模块System.Random
)的示例将要求您运行:
$ stack install random
并重新启动翻译。
由于Stack有点复杂,并且您在开始时并不真正需要它提供的功能,因此您可能会发现在您开始使用时Haskell平台更易于使用。 (" Generic"安装程序应该可以在你的发行版上正常工作。)它随附了所有安装的内容,你使用它的方式将更加符合LYAH中描述的内容。与haskell-mode
一起,你应该有一个相当不错的Haskell环境。
一般来说,堆栈和Haskell平台并排安装应该没有问题(Haskell平台实际上包含堆栈的事实证明了这一点)。 Stack将在" $ HOME / .stack"下单独维护所有内容。子目录,因此编译器或包之间不会有任何干扰。请注意,在此设置中,您将使用cabal
来管理安装在平台端的软件包,并stack
- 显然 - 用于管理堆栈端的软件包。
如果您想坚持使用纯粹的Stack安装,我可能会在您开始时建议以下工作流程:
您将看到使用" stack new"创建的Stack项目的引用。或者"堆栈初始化"。在开始时避免这些,并坚持堆栈"全球项目"。这是在运行" stack"时将生效的隐式项目。在一个没有" stack.yaml"的目录中。文件(直接或在父目录中):
$ cd
$ stack path --project-root
/u/buhr/.stack/global-project
$
当您在全局项目中工作时(即,不在stack.yaml
文件下的某个地方),您可以使用以下命令调用解释器和编译器:
$ stack exec ghci
$ stack ghc -- -O2 Hello.hs
他们都可以访问您使用以下命令安装的任何其他库(包):
$ stack install random
已更新:关于stack ghci
和stack exec ghci
之间差异的说明。前者旨在在本地项目的上下文中运行GHCi(即,在stack.yaml
文件下工作)。它传递一些额外的标志来隐藏全局安装的包,并自动从包中提供可用的模块。在全球项目中工作时,除了stack ghci
产生警告之外,我认为没有任何实际差异;无论您使用哪种,您都需要使用:load Whatever.hs
明确加载自己的模块。关于this Stack documentation page的差异有更多信息,特别是在它试图解释差异的底部。
最终,您可以切换到使用Stack项目的工作流程。这将涉及使用stack new
创建一个新的Stack项目目录,stack setup
将私有编译器版本安装/链接到该目录,然后修改项目的xxx.cabal
文件(并且可能是其stack.yaml
文件)以指示需要哪些附加包,而不是使用stack install
。当你只是想开始编写代码时,这有点复杂。
您可能还会看到Intero的参考,这是专为Stack设计的Emacs模式。 Intero非常好用,但在处理全局项目中的文件时它并不能很好地工作。它倾向于想要在目录"〜/ .stack / global-project"中启动解释器,这是非常没用的。 (我使用Intero,但我已修补它在这方面表现得更好。)
最好坚持使用" haskell-mode"相反,当你开始使用非全球项目时,请考虑Intero。我建议安装" haskell-mode"来自MELPA的说明,但在您的.emacs
文件中添加以下内容,而不是文档中建议的内容:
(require 'haskell)
;; add capability to submit code to interpreter and mark errors
(add-hook 'haskell-mode-hook 'interactive-haskell-mode)
;; add missing keybindings for navigating errors
(define-key interactive-haskell-mode-map (kbd "M-n") 'haskell-goto-next-error)
(define-key interactive-haskell-mode-map (kbd "M-p") 'haskell-goto-prev-error)
(define-key interactive-haskell-mode-map (kbd "C-c M-p")
'haskell-goto-first-error)
;; merge this with your existing custom-set-variables
(custom-set-variables
;; NOTE: include following line to work around haskell-mode
;; bug if using GHC >= 8.2.1.
;; See: https://github.com/haskell/haskell-mode/issues/1553
'(haskell-process-args-stack-ghci
'("--ghci-options=-ferror-spans -fshow-loaded-modules"
"--no-build" "--no-load"))
;; some options suggested in the haskell-mode documentation
'(haskell-process-auto-import-loaded-modules t)
'(haskell-process-log t)
'(haskell-process-suggest-remove-import-lines t)
;; make sure "stack ghci" is used, even in the global project
'(haskell-process-type 'stack-ghci))
我使用" haskell-mode-20171022.26"进行了纯粹的Stack安装测试,看起来效果很好。我可以在全局项目中加载一个新的Haskell文件,使用" C-c C-l"将其提交到交互式会话,并使用" M-n"浏览源文件中突出显示的错误。和" M-p"。 (错误出现在迷你缓冲区中。)
如果您决定使用Haskell平台,我认为所有这些" haskell-mode"配置仍将适用,但您应删除最后一个自定义行。 (haskell-process-type
的默认auto
会选择合适的内容。)
希望有所帮助!
答案 1 :(得分:5)
你有三个选择。
这是一种可能性,但不是一个受欢迎的选择,出于很多原因你会在适当的时候发现,如果你选择这样做。您将获得更好的体验,并使用Stack或Nix获得很多更好的支持。这两个人中的哪一个似乎主要是关于个人偏好。它们是不同的野兽,但对于初学者而言,差异不会立即明显,因此您无法做出“明智的决定”。只需选择一个并稍后重新评估。
我建议任何想要快速开始使用Haskell的人(不熟悉Nix)。期。你不需要单独安装任何东西,Stack会为你处理所有Haskell的东西。您通常不会直接使用Stack与cabal。 stack build
在内部使用cabal,但您无需担心。有一点需要注意,Stack不是包管理器。这是一个构建工具。它通常不会安装任何东西。但它会获取所需的所有依赖项,并将它们与其他内容一起存储在~/.stack
中。
这是我个人使用的所以我可能有偏见,但我认为从长远来看这是最好的解决方案。需要注意的是,学习曲线相当陡峭,开始时你有很多机会射击自己。
我强烈建议从Stack开始,但随着你对Haskell的旅程继续保持对Nix的开放态度。