How can I use `cabal repl` instead of `ghci` in `ghc-mod`? - haskell

I want to use cabal repl to instead of ghci (. My goal is being able to use other modules in my project ).

My setups uses this:
(setq haskell-program-name "cabal repl")
(setq haskell-ghci-program-name "cabal repl")
(custom-set-variables
;; ...
'(haskell-process-type 'cabal-repl)
;; ...
)
concerning ghc and cabal and is running fine as it is (current ghc-mod and emacs 24.3.1)

GHC-mod has an issue about this, where the author suggests changing the GHCi executable:
(setq haskell-ghci-program-name "cabal")
(setq haskell-ghci-program-args '("repl"))

You should consider to setup Haskell Interactive Mode.
Unlike Inferior Haskell Mode, this mode is deeply integrated into Cabal. It does not only use cabal repl, but also interprets Cabal error messages and suggests to add imports or language extensions, and provides completion for modules.

Related

Compiling a haskell script with external dependencies without cabal

I'm relatively new to Haskell and I realize I might be swimming against the stream here, but nonetheless, I'll ask:
Say I have a short Haskell script:
import Data.List.Split (splitOn)
main :: IO ()
main = do
let orders = splitOn "x" "axbxc"
putStrLn $ head orders
If I used only standard functions I could compile this with ghc <script.hs>. Because I depend on the split package to provide the splitOn function, the compilation fails.
Now, I have no difficulties setting up a cabal project with a project.cabal and a Setup.hs file in order to get this to actually compile. However, this feels like a lot of extra boilerplate for a standalone script.
So, is there a way to compile a single .hs file against some external package? Something similar to what in Python would be done by pip install something, "installing the package into the interpreter", i.e. is there a way to install extra packages "into ghc", so that I for instance only need to provide some extra linking flag to ghc?
The Cabal equivalent of the Stack script in bradrn's answer would be:
#!/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
The script can be run with cabal run, or directly by giving it execute permission. If need be, version bounds can be added as usual to the build-depends on the top of the script.
(Note this isn't literally a solution without Cabal, as doing this with GHC alone, even if it is possible, wouldn't be worth the trouble. In any case, it certainly avoid the boilerplate of needing multiple files.)
If you use Stack, the simplest way to do this is to write a ‘Stack script’, which is a Haskell file with a description of the required packages in the first line (really an invocation of stack specifying the appropriate command line arguments). An example (slightly modified from the 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!
This script uses the turtle package; when run, Stack downloads and builds this dependency, after which it is available in the script. (Note that the second time it is run, turtle has already been built so does not need to be rebuilt again.)
As it happens, the --package command in Stack is not limited to scripts. It can be used with other Stack commands as well! For instance, to compile your program, you should be able to run stack ghc --resolver lts-16.27 --package split -- -ghc-options your-program-name.hs. And stack ghci --package split will give you a GHCi prompt where you can import Data.List.Split.
(Note: This answer focuses on Stack rather than Cabal, simply because I don’t know Cabal very well. However, I believe all this can be done using Cabal as well. For instance, I do know that Cabal has something very similar to the Stack scripts I mentioned above, though I can’t remember the syntax just at the moment.)
EDIT: See #duplode’s answer for how to do this with Cabal.
You can install into the default environment for the current user by doing cabal install --lib split. The package should then be available to ghc and ghci without needing any special options.
More information is at the bottom of this section in the Cabal manual. The v2 commands that it uses are the default now so if you have a fairly new cabal you can just use install rather than v2-install.
I think this is the quintessential entry point to the package management battle in Haskell. It's not there's not enough advice, but there's so much, each with its own caveats and assumptions. Climbing that mountain for the sake of splitOn feels to the newbie like they're Doing It Wrong.
After spending far too much time trying each permutation, I've collated the fine answers here, and many, many others from elsewhere, put them to the test, and summarised the results. The full write up is here.
The pertinent summary of solutions is:
Install globally
You can still do global installs with cabal install --lib the-package.
Use Stack as a run command
You can use stack directly, eg: stack exec --package containers --package optparse-generic [...and so on] -- runghc hello.hs
Create a Stack project
The real deal. Run stack new my-project hraftery/minimal, put your code in Main.hs and your dependencies in my-project.cabal (and maybe stack.yaml - check the article), and then run stack build to automagically pull and build all dependencies.
Use a Stack script
Make your Haskell file itself an executable Stack script. Add -- stack --resolver lts-6.25 script --package the-package to the top of your .hs file and set its executable bit.
For my Edit/Test/Run workflow (eg. using VS Code, GHCi and GHC respectively), I found it pretty clear what works in practice. In summary:
Amongst a chorus of discouragement, Global Installs suit what I know of your use case just fine.
Where Global Installs don't make sense (eg. for managing dependency versions or being portable) a Stack project starting from my minimal template is a smooth transition to a more sophisticated and popular method.

Haskell cabal repl - error: Variable not in scope: main

Issue can be reproduced by running cabal repl for Haskell Editor Setup project. Build instructions are here. After cabal repl loaded evaluate main and it will print following error:
<interactive>:1:1: error: Variable not in scope: main
You can see entire project at: Haskell Editor Setup project
The haskell-editor-setup.cabal has main-is: Main.hs so I do not understand why it is not activated on cabal repl run.
I am also using ide-haskell-repl Atom extension which gives a REPL inside Atom and it works fine even though it is set to run by using cabal repl.
I am not sure whether this is a bug in cabal or something I am doing wrong. Any advice on how to fix this?
Running :m *Main or :m +Main in cabal repl will fix the issue but what I am looking for is to fix cabal repl run so that it loads Main properly.

How to set up org-babel for Haskell with Stack

I'm running:
GNU Emacs 24.4.1
Stack Version 1.3.3
org-mode
haskell-mode
I've looked through:
Emacs Org-Mode & Literate Haskell
https://gist.github.com/reetinder/4022989
https://wiki.haskell.org/Emacs/Literate_programming
https://wiki.haskell.org/Literate_programming
https://github.com/haskell/haskell-mode/issues/1429
While the gist above looks promising, I haven't found anything that looked to be an authoritative way to get org-haskell running (eg, nothing on melpa), and certainly nothing aimed specifically at whatever intricacy running a stack environment rather than using my global ghc would entail.
When I try to:
#+BEGIN_SRC haskell
let x = "test"
putStrLn x
#+END_SRC
I get
executing Haskell code-block
...which hangs forever. When I C-g, I see:
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Some flags have not been recognized: prompt2, ghci |
ghci λ> let x = "TESTING!"
putStrLn x
"org-babel-haskell-eoe"
Prelude|
<interactive>:4:1: parse error on input `putStrLn'
ghci λ> "org-babel-haskell-eoe"
When I tab to the haskell buffer, I see it has genuinely evaluated what I sent, it just has this org-babel-haskell-eoe error and never returns control to my org session.
Any chance this is because I have a custom prompt? Using the lambda instead of Prelude> ?
This is not a complete answer: in particular, it does not even mention Stack. But I (a complete ignoramus on Haskell) wanted to find out what it would take to get the OP's test program to run in babel. Here's what I found:
You need a haskell interpreter ;-) I'm on Fedora 24, so I installed the ghc-compiler package and I got ghci.
You need haskell-mode. I installed that from MELPA, using the emacs package manager. That also installed inf-haskell.el
By default, inf-haskell wants to run hugs, so I customized haskell-program-name and set it to "ghci".
M-x load-library RET ob-haskell RET
C-c C-c on the code block: the first time it fails and the Messages buffer shows "Buffer haskell.org does not exist or has no process".
But if you do it C-c C-c on the code block again, it succeeds!
Obviously, ob-haskell.el needs some work - and that's before we even get to Stack, of which I know even less than I know of Haskell, so I'll leave that as an exercise for the interested reader :-)
EDIT: Re. version info (requested in a comment): I keep close to the bleeding edge. At this point in time (2017-05-01), I run Org mode version 9.0.5 (release_9.0.5-444-g998576 # /home/nick/elisp/org-mode/lisp/) and GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.20.10) of 2017-04-14
It is probably because of the custom prompt: I had the same issue, and when I removed ":set +t" and ":set prompt "GHCI >" from ~/.ghci, it worked. I fiddled with it some, and it seems it will work so long as your custom prompt doesn't have any spaces in it except the end (I changes mine to "GHCI> " and it works). It seems to be that the regular expression it parses the information from assumes the prompt will have no spaces in it.
In my case it was .ghci, like Testare's. As soon as I commented out :set prompt "λ ", emacs stopped freezing but gave the message ‘org-babel-script-escape’ expects a string. It was necessary to comment out :set +t for it to work.
what i did after installed stack and ghci (with stack itself)), was to install intero in emacs and then add those to init.el:
(setq haskell-process-type 'stack-ghci)
((org-babel-do-load-languages
'org-babel-load-languages
'((haskell . t)))
after that i can C-c C-c in haskell code block and i get a result under the code block.

Minimal cabal file for use in sandbox

I’m trying to write a project with the Hakyll library. In order to avoid messing up with my system, I’d install it in a cabal sandbox in the same folder where my Hakyll project lives.
Being more or less a beginner, I’m still struggling with getting the pest practices right. A simple approach would be to just do
$ cabal sandbox init
$ cabal install hakyll
$ cabal exec ghc -- --make site.hs
where the last line compiles my Hakyll generator using the libraries in the sandbox. The obvious disadvantage is that this is not reproducible. The main version of Hakyll could have change when I try to run it again from a clean checkout.
Another approach would be to write a proper project.cabal file (For example like this: chromaticleaves.cabal) and then do cabal install or cabal run.
However, I feel that this may be a bit too much information. As I do not intend to publish this project any more than needed, I’m not really convinced I need to put a project name and version number in there. (For example, in a Ruby Gemfile, I would also only specify the libraries and nothing else unless I wanted to publish a gem myself.)
So, eventually I figured that with a file like
$ cat project.cabal
cabal-version: >= 1.2
library
build-depends: base >=4.6
, containers
, process
, hakyll >=4.5
, pandoc
, pandoc-types
I can type
$ cabal sandbox init
$ cabal install --only-dependencies
$ cabal exec ghc -- --make site.hs
and it seems to download all dependencies and is able to compile the file.
Is this a reasonable approach or is the best practice really to give a full specification with name, version and executable sections in the cabal file?
Edit: Apparently, my approach does not let me do cabal repl. So either there exists a completely different way of doing it or it seems I have to go with a fuller specification.
I use your first approach myself for my Hakyll-based webpage. You don't need to create a .cabal file to pin the Hakyll version, you only need to add the following line to cabal.config:
constraints: hakyll == 4.5
I think that cabal repl will work with this approach, but you will need to load site.hs manually (:l site.hs). Or you can use cabal exec ghci -- site.hs.

cabal sandbox + haskeline

cabal sandbox init
cabal install haskeline
... installs successfully ...
ghci
Prelude> :module +System.Console.Haskeline
<no location info>:
Could not find module `System.Console.Haskeline'
ghc-pkg list haskeline
.. not found ..
What do I have to do get haskeline to work with cabal sandbox? If I install haskeline normally (no sandbox) it is fine (ghc-pkg list haskeline -- found it).
Either use cabal repl like Joseph mentioned or you can explicitly pass the package db to the GHCi shell relative to your current working directory.
ghci -no-user-package-db -package-db .cabal-sandbox/*-packages.conf.d YourModule.hs
It's recommended that you just use cabal.
In order to get ghci to use a local sandbox you must (a) set up a my-project.cabal file and (b) use cabal repl.

Resources