Module loading options in GHCi - haskell

Why does GHCi have so many different commands for loading modules into a session?
Here are ones I'm aware of, together with their rather confusing explanations from :help in ghci:
add [*]<mod> -- add module(s) to the current target set
:module [+/-] [*]<mod> -- set the context for expression evaluation
:load [*]<mod> -- load module(s) and their dependents
:reload <mod> -- reload the current module set. (Note: :help doesn't say that this can take a module argument, but it seems that it can.)
import Mod
What do they each do? How does the asterisk change it? Why are there so many? :(

There are essentially two different concepts at work here: target set and evaluation context.
You work with the target set with :add, :load and :reload, and you work with the evaluation context with :module and import.
The target set is the list of locally available modules that ghci is reading and compiling. Generally you would use this to specify the source that you're working on. ghci will load and compile each of these modules and any dependencies it needs.
You use :load to reset the target set to precisely the given set of modules, and :add to add the given modules to the existing target set.
If you specify modules in the target set with * then they will always be "bytecode-interpreted" - which means they load quickly but don't run as fast as compiled code - otherwise ghci will use a compiled object file if available and bytecode interpret if not.
:reload on its own reloads the entire target set and dependencies. I'm not quite sure exactly what :reload <mod> does but I think it reloads <mod> and dependencies and leaves the rest untouched.
The evaluation context controls what names are in scope at the prompt, and is fully documented here. Modules for adding to the evaluation context can either be local ones in the target set+dependencies, or be "package" ones that have been previously registered with ghc using the ghc-pkg tool (or cabal which calls that eventually). import Foo is just another way of writing :module +Foo.
NOTE: this answer is a mixture of my intuitive understanding from my experience of using ghci and just reading the documentation and trying to integrate the two in my mind. So I may well not have got this 100% accurate!

Related

cabal repl gives error "cannot find module" but it is listed as dependency and cabal build works

I have a project with a a library in a few directories. The cabal file is produced with hpack and looks ok. The project builds with cabal build and the main can be run with cabal run xx.
Using repl in vscode, I get occasionally
Could not load module ‘GIS.Subdivisions’
It is a member of the hidden package ‘CatCoreConcepts-0.2’.
Perhaps you need to add ‘CatCoreConcepts’ to the build-depends in your .cabal file.
The package is, of courese, listed in the dependencies. The error is not always occuring and I assume it is a probem with some data cached in the vscode Haskell HLS plugin. Is there a simple way to clean the cache of the plugin? Restart HLS and Developer: reload window in vscode is not having any effect.
I have had the problem where VSCode thinks modules are hidden. Many answers on SO, such as this one. Possible solution, which hopefully helps,
ghc-pkg expose CatCoreConcepts
This is not an answer to the main question, but to some OP comments.
I'd say cabal documentation is good (but lengthy).
A brief summary as I understand (not official documentation)
A Package is a set of components
A component is a set of modules (haskell files)
Module-name and file-name must be equal except for entrypoints (see below)
Components can be classified in two groups:
runnables: tests, benchmarks and executables
runnables must have a unique main function called the entrypoint
In the cabal file, you can use keywords executable, test-suite and benchmark for defining runnables
Within each runnable section in the cabal file there must be a field main-is pointing to the file with the entrypoint
The file-name of the entrypoint can be whatever but the module name must be Main.
Notice that runnable components can have multiple modules (haskell files). For example you can have a test suit consisting in a file with auxiliar functions and other file with the main function. Both files conform a component (a test-suite in this case)
non-runnables: libraries
In the cabal file, you can use keywords library for defining non-runnable component
For libraries you must specify the modules which are exposed with the exposed-modules keyword.
Runnable components can import non-runnable ones even if they are defined in the same package. But viceversa is not true.
As a good practice, each component should be separated in a different folder. Some libraries expect naming convention. For example: tests to be in a folder with the same name and with test_XXXX.hs format (this is regular across programing languages, not only Haskell)
When libraries are separated in folders the field hs-source-dirs must be specified to point to the folder with the haskell files
(the name runnable is not part of the official docs, but is the way I understand)
stack works pretty much the same as cabal since the former is just a different front-end for the later. So aside from different keywords and yaml format, all of the above can be applied to stack (notice that cabal updates more often than stack, therefore some features supported by cabal can be missing in stack.)
If you find this useful, I think I am opening an issue to the cabal docs to include it.

Finding unused Haskell functions in a module or file?

Is there a way to automatically find unused functions (and constants) in a module or .hs file? Specifically, I mean those functions that are not used (directly or indirectly) by the functions in the export list of the current module/file.
I know that e.g. Emacs haskell mode has the ability to warn about unused importS as follows:
The import of XXX is redundant
Is there similar tool or method for finding unused functions?
Note: I know this can be done manually by deleting some code and see whether it still compiles. But it's tedious process.
Here are some relevant ghc -W flags:
-Wunused-binds
-Wunused-do-bind
-Wunused-foralls
-Wunused-imports
-Wunused-local-binds
-Wunused-matches
-Wunused-pattern-binds
-Wunused-top-binds
-Wunused-type-patterns
Or just use -Wall. You can get a complete list of ghc flags with ghc --show-options.

How to load imports automatically in cabal repl?

I am under the impression that until recently cabal repl automatically imported all the imports from the currently loaded file. That is if I had a file src/Main.hs:
module Main where
import qualified Data.Vector as V
main = putStrLn "foo"
And I would load it in cabal repl with :l src/Main.hs, V would be available without any further work.
I believe this behavior changed during the change to ghc/ghci 7.10, but I am not sure. Is there any option that would let me change that back to the way it was before?
edit: As it happens I have actually compiled the modules, which was part of the problem. See Ørjan Johansens comment below.
From the GHC User's Guide:
The syntax in the prompt *module indicates that it is the full top-level scope of module that is contributing to the scope for expressions typed at the prompt. Without the *, just the exports of the module are visible.
NOTE: for technical reasons, GHCi can only support the *-form for modules that are interpreted. Compiled modules and package modules can only contribute their exports to the current scope. To ensure that GHCi loads the interpreted version of a module, add the * when loading the module, e.g. :load *M.
In other words, add a * before the module name when loading.

A workaround for the “Template Haskell + C” bug?

I've got the following situation:
Library X is a wrapper over some code in C.
Library A depends on library X.
Library B uses Template Haskell and depends on library A.
GHC bug #9010 makes it impossible to install library B using GHC 7.6. When TH is processed, GHCi fires up and tries to load library X, which fails with a message like
Loading package charsetdetect-ae-1.0 ... linking ... ghc:
~/.cabal/lib/x86_64-linux-ghc-7.6.3/charsetdetect-ae-1.0/
libHScharsetdetect-ae-1.0.a: unknown symbol `_ZTV15nsCharSetProber'
(the actual name of the “unknown symbol” differs from machine to machine).
Are there any workarounds for this problem (apart from “don't use Template Haskell”, of course)? Maybe library X has to be compiled differently, or there's some way to stop it from loading (as it shouldn't be called during code generation anyway)?
This is really one of the main reasons that 7.8 switched to dynamic GHCi by default. Rather than try to support every feature of every object file format, it builds dynamic libraries and lets the system dynamic loader handle them.
Try building with the g++ option -fno-weak. From the g++ man page:
-fno-weak
Do not use weak symbol support, even if it is provided by the linker. By default, G++ will use weak symbols if they are available. This option exists only for testing, and should not be used by end-users; it will result in inferior code and has no benefits. This option may be removed in a future release of G++.
There is another issue with __dso_handle. I found that you can at least get the library to load and apparently work by linking in a file which defines that symbol. I don't know whether this hack will cause anything to go wrong.
So in X.cabal add
if impl(ghc < 7.8)
cc-option: -fno-weak
c-sources: cbits/dso_handle.c
where cbits/dso_handle.c contains
void *__dso_handle;

Haddock link to functions in non-imported modules

In module B I have documentation with a link 'A.foo', linking to the foo member of module A. In module A I import module B. Haddock renders this as a link to A.html#t:foo, namely pointing at the type foo (which does not exist) not the function foo, which is at A.html#v:foo.
Why does Haddock link to t: for variables that start with a lower case letter? Is that a bug? For 'A.Foo' I can see that it could be a type or a constructor, so there are namespacing issues. For foo it seems a variable is at least most plausible.
Is there any way to fake a link? I am writing this in code samples, so I need it to be rendered as foo. I tried anchors, but they render as the module name, and for direct hyperlinks you have no control over the displayed text.
I considered a post processor (replacing t:[a-z] with v:), but that requires a custom Setup.hs which causes problems and is quite ugly.
I couldn't find any Haddock command line flags to obtain a more reasonable behavior, such as specifying that foo is a variable.
I can't add an import of A to B without introducing circular imports, which is vile to add purely for documentation.
I am running into this problem in the Shake documentation, where as an example removeFilesAfter does not get the right link.
I can partially answer the the first question (Why?); not sure if it is a bug or desired behaviour.
When haddock resolves references in LexParseRn.rename, it tries to look up the identifier in the environment (via lookupGRE_RdrName). This ought to fail. Next it looks as what the thing could mean (using dataTcOccs from GHC’s RnEnv). The relevant lines are:
dataTcOccs :: RdrName -> [RdrName]
-- Return both the given name and the same name promoted to the TcClsName
-- namespace. This is useful when we aren't sure which we are looking at.
dataTcOccs rdr_name
[...]
| isDataOcc occ || isVarOcc occ
= [rdr_name, rdr_name_tc]
[...]
where
occ = rdrNameOcc rdr_name
rdr_name_tc = setRdrNameSpace rdr_name tcName
so it returns the name first interpreted as whatever it was before (likely a link to a value), and then interpreted as a type constructor. How can a regular name be a type constructor? My guess is that this was added when TypeOperators were reformed in GHC 7.6, which now do share the namespace with value-level operators.
Then haddock matches on the result: If the first one is a type constructor, use that, otherwise use the second. So either it was a type constructor before, then this is used. Or it was not, but then the modified version generated by dataTcOccs is to be used.
It seems to me that haddock should just always use the first option here, and the code is just a mislead copy from how multiple results are used when they can actually be resolved.
This was a Haddock bug #228 and Neil's Haddock bug #253 and the fix has been upstream for few months. You can build GHC HEAD and rebuild your documentation or wait for 7.8 and do it then.

Resources