How to tell HSpec where to look for the source files to be tested - haskell

I'm new to Haskell and I wanted to add tests to my first project. I chose HSpec for this. My only spec file doesn't contain anything special so far. I just copied the example from the HSpec website and added import statements for my own modules to be tested. When I try to run it via runhaskell test/XSpec.hs it complains that it "could not find module X". How do I tell it about the load paths it should take a look into before complaining?

Adding -isrc helped, so the call looks like this:
runhaskell -isrc test/Spec.hs
Additionally, it is important to note, that a module's file name should match the module name, including the case. I.e. the filename of the module Foo should be Foo.hs.

Related

Cabal update now can't load any modules from "hidden packages"

I've been working on a project and recently I did a cabal update.
I usually roll into ghci like:
$ ghci -package-db ~/.cabal/store/ghc-8.10.7/package.db
After the update loading module in my project results in even the basic Haskell modules like System.Random or MonadIO fails with the following errors when trying to load my own module called ProcessIO:
ProcessIO.hs:50:1: error:
Could not load module ‘Data.IORef.MonadIO’
It is a member of the hidden package ‘monadIO-0.11.1.0’.
You can run ‘:set -package monadIO’ to expose it.
(Note: this unloads all the modules in the current scope.)
Locations searched:
Data/IORef/MonadIO.hs
Data/IORef/MonadIO.lhs
Data/IORef/MonadIO.hsig
Data/IORef/MonadIO.lhsig
I checked that maybe the .cabal file build-depends versions might have been altered, but the cabal package.db directory contains all the right versions of the dependencies in the .cabal file. For example the error above complains abot monadIO-0.11.1.0 being hidden however: in package.db/ we see the right version exists:
monadIO-0.11.1.0-0aec75273f3fef94783e211a1933f8ac923485a963be3b6a61995d4a88dd1135.conf
I should say I haven't looked at the package.db files before because everything simple worked so there may be something telling about the .conf file name that signals something is wrong.
Either way, can't build anything and I need some help!
EDIT: posting my default environments file ~/.ghc/x86_64-linux-8.10.7/environments/default in case it matters:
clear-package-db
global-package-db
package-db /home/surya/.cabal/store/ghc-8.10.7/package.db
package-id ghc-8.10.7
package-id bytestring-0.10.12.0
...
(Let me know if I need to share more of it... or less)

Why can't the ghci find the hs file that I am trying to compile?

I'm learning Haskell for the first time and I can't see to understand why the ghci can't find the file I'm trying to compile. Especially since, I saved the file. This is my file,
import System.IO
trueAndFalse = True && False
Now this is what I ran in the compiler,
<no location info>: error: can't find file: tut-1.hs
Failed, no modules loaded.
The "Failed, no modules loaded." makes me think you're talking about ghci. If so, you can find out where ghci is looking for files with :show paths. Here's what it looks like when I try:
> :show paths
current working directory:
/home/<my username>
module import search paths:
.
The module import search paths tells you what directories it's looking in. A lone . in that list refers to the current working directory. So, for me, if I wanted a file to be easily accessible from that ghci instance, I would have to save it in /home/<my username>.
Of course there are ways of changing all of these pieces -- which paths are in the import search path, which directory is the current working directory, and so forth -- but this should get you going for simple usage.
And, by the way, a note on terminology: the GHC tool suite comes with both a compiler and an interpreter. The compiler's executable is ghc, and the interpreter's executable is ghci. Knowing about that distinction may help you avoid confusion in future conversations!

Typechecking multiple 'Main's

I have a Haskell library with several executables (tests, benchmarks, etc), in total about six. When I do some refactoring in the library, I usually need to make some small change to each of the executables.
In my current workflow, I separately compile each executable (say, with GHCi) and fix each one up. This is tedious because I have to type out the path to each executable, and moreover have to reload all of the (very large) library, which even with GHCi takes some time.
My first thought to solve this issue was to create a single dummy module that imports the executable "Main" modules. However, this (of course) requires that the "Main" modules have a module name like module Executable1 where .... But now cabal complains when compiling the executable that it can't find a module called "Main" (despite explicitly listing "main-is" in the cabal file for each executable.)
I also tried ghci Exec1.hs Exec2.hs ..., but it complains module ‘main#main:Main’ is defined in multiple files.
Is there an easy way to load multiple "Main" modules at once with GHCi so I can typecheck them simultaneously?
Cabal’s main-is option only tells Cabal what filename it should pass to GHC. Cabal does not care about it’s module name.
GHC itself has a flag, also called -main-is, documented here which tells the compiler what module conains the main function.
So this works:
executable foo
main-is: Foo.hs
ghc-options: -main-is Foo
Of course Foo.hs should start with module Foo where… and export main. As usual, the module name and file name needs to match.
This way, all executable can have different module names and you can load them all in GHCi.
If you also want to change the name of the main function, write ghc-options: -main-is Foo.fooMain. I would guess you could even have all executables have the same module but different main-functions this way.

GHCi cannot find modules of my program

I'm working on a project and I'm using Cabal for management. I've specified directory of source files, modules, all the stuff. All my files have the same names as their corresponding modules, case is preserved.
I can do:
$ cabal configure
$ cabal build
without problems.
However, imagine I have a module Module in file Module.hs, and file File.hs in the same directory. Now, when I'm trying to load File.hs from Emacs for testing, I get the following:
____Could not find module ‘Module’
It is a member of the hidden package ‘ghc-7.8.3’.
Use -v to see a list of the files searched for.
Failed, modules loaded: none.
Full contents of File.hs:
module File where
import Module
How to make it find files of my project?
You can launch the REPL via Cabal like so:
# cabal repl
This is the same as running ghci, but will take into account any additional dependencies installed by cabal install your local or sandbox package repository.
You need to tell GHCi where to find your source files. For example, if your project directory is ./foo and you have your source files in ./foo/src you need to say (from your project directory):
:set -isrc
at the command prompt in GHCi. You will then have access to private members in your sourc file loaded with C-c C-l.
You also need to make sure that you haven't cabal installed your package, otherwise the package will be loaded, not the project source files.
I had the same problem, fixed it, and decided to write about my troubleshooting. This might help new people learning Haskell. Read on.
I was playing around with this example code.
http://zvon.org/other/haskell/Outputdirectory/getCurrentDirectory_f.html
Code:
import Directory
main = aaa "/tmp/FOO"
aaa ddd = do createDirectory ddd
setCurrentDirectory ddd
d <- getCurrentDirectory
print d
writeFile "aaa" "HELLO"
l <- getDirectoryContents d
print l
I noticed that they are using this package.
https://hackage.haskell.org/package/directory-1.3.6.2/docs/System-Directory.html
So I installed it with this commands:
cabal update
cabal install directory
Compiling the example code with ghc failed with this error message.
Could not find module `Directory'
Use -v to see a list of the files searched for.
|
4 | import Directory
| ^^^^^^^^^^^^^^^^
I was stuck for a while until I changed the import line to this:
import System.Directory
After this change ghc could compile successfully.
Conclussion: are you sure you are importing properly?

Different behavior of cabal repl for library vs. executable

Using cabal repl seems to do nothing at all when used on library projects, but works fine for executable projects. Is this expected behavior that I just don't understand?
If I have a file containing simply
go = putStrLn "test"
and use cabal init with all the defaults (but choose "library" as the type), then running cabal repl just produces the some text about configuring and preprocessing the library and never enters a REPL environment. The exact same steps, but with "executable" selected as the type, puts me right into GHCi as expected.
The code works fine when loaded directly into GHCi.
For cabal repl to load your modules, you have to first name them in code and then specify them in your project's .cabal file as exposed:
-- MyModule.hs
module MyModule where
go = putStrLn "test"
-- MyProject.cabal
name: MyProject
-- other info ...
library
exposed-modules: MyModule
-- other options ...
Then when you run cabal repl, it'll have access to everything in your sandbox (if present) and the exposed modules. It might also work if you specify them as other-modules instead of exposed-modules, but I haven't tried that one out.

Resources