How to load imports automatically in cabal repl? - haskell

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.

Related

Is it possible to trace the chain of imports that lead to a particular identifier?

A Haskell package (let's call it package A) has stopped compiling for me due to updated dependencies, with an error about an undefined variable. I have access to an old environment of dependencies where the exact same code does still compile, so I can open the module in GHCi and use :info to track down where it originally came from, which leads me to package B.
The trouble is that the now-broken module in A does not directly import the module from B defining this missing identifier; it must have been getting it through another import that re-exports it. But neither A nor B have changed at all changed between the two environments. So that means that a module in some third package C must previously have imported and re-exported my the identifier from B, to then be imported (possibly via further re-exports) by the broken module in A, and C has changed between the two environments to no longer re-export the identifier.
Is there some way I can ask GHC or Cabal in the working environment for the full chain of imports that leads to an identifier being in scope, so that I can identify the package C? Otherwise I don't know how to narrow down the cause of the problem without manually reviewing all of the (transitive) dependencies of A that could plausibly import something from B.
I don't know a way to ask for the whole chain, but you could use -ddump-minimal-imports to ask for the first step in the chain, then iterate.

What does a quoted string in the import syntax `import "cryptonite" Crypto.Hash` mean?

As stated in the title. There is a codebase, where I have seen the following syntax
import "cryptonite" Crypto.Hash
(Context, Digest, SHA256, hash, hashFinalize, hashInit,
hashUpdate)
This syntax doesn't seem to be mentioned on haskell wiki on imports.
What does the "cryptonite" string do here?
Where does this syntax come from?
Is is part of Haskell2010 and if it is so where in the language report is it mentioned?
This is extra syntax that is supported when using the PackageImports extension:
With the PackageImports extension, GHC allows import declarations to
be qualified by the package name that the module is intended to be
imported from. For example:
import "network" Network.Socket
would import the module Network.Socket
from the package network (any version). This may be used to
disambiguate an import when the same module is available from multiple
packages, or is present in both the current package being built and an
external package.
The special package name this can be used to refer to the current
package being built.
It occasionally happens that two packages export a module with the same name. For example both hashmap and unordered-containers export Data.HashSet. If both packages are installed, we want to disambiguate between the different packages. With this type of import, the author thus specifies that the Crypto.Hash module of the cryptonite needs to be used.
This is to to the best of my knowledge not standard Haskell (in the sense that other Haskell compilers do not have to support this, it seems not specified in the import statement section of the Haskell 2010 report), but a Glasgow Haskell compiler extension. Of course other compilers can support this as well, but a compiler without this extension, can still rightfully call itself a "Haskell compiler". In order to activate this extension, you need to compile with the -XPackageImports extension:
ghc -XPackageImports main.hs
This is a dynamic flag, and thus can be specified in the "pragma" of a Haskell source file as well.

Module-level tests in Haskell

I am getting acquainted to Haskell, currently writing my third "homework" to some course I found on the web. The homework assignment needs to be presented* in a file, named Golf.hs, starting with module Golf where. All well and good, this seems to be idiomatic in the language.
However, I am used to python modules ending in if __name__ == "__main__:, where one can put tests over the module, including during module development.ghc doesn't seem happy with such an approach:
$ ghc Golf.hs -o Golf && ./Golf
<no location info>: error:
output was redirected with -o, but no output will be generated
Even though using cabal seems to be the norm, I would like to also understand the raw command-line invocations, that make programs work. ghci seems to be another approach to testing newly written code, yet reloading modules is peta. What is the easiest way to write some invocations of my functions with predefined test data and observe on stdout the result?
* - for students, who actually attend the course, I just follow the lecture notes and strive to complete the homeworks
Golf2.hs:
{-# OPTIONS_GHC -Wall #-}
module Golf2 where
foo :: Int -> Int
foo n = 42
main = putStr "Hello"
The output:
$ ghc Golf2.hs -o Golf2
[1 of 1] Compiling Golf ( Golf2.hs, Golf2.o )
Golf2.hs:6:5: warning: [-Wunused-matches] Defined but not used: ‘n’
Golf2.hs:8:1: warning: [-Wmissing-signatures]
Top-level binding with no type signature: main :: IO ()
<no location info>: error:
output was redirected with -o, but no output will be generated
because there is no Main module.
ghci is a really useful tool for learning!
When you only have one module, it's very easy, too. Start ghci, then :l Golf.hs. This will load your file. Then you'll be able to type foo 342 and see "42" displayed, or main and see "hello". You can edit the file, then use :reload or :r to load your changes. Real World Haskell has a good intro to using ghci.
This is a little easier than using ghc or tools like cabal, and all you really need while you're learning the very basics.
If you want to use ghc-the-compiler (instead of its interactive variant ghci), you might use the -main-is option.
From the docs:
-main-is⟨thing⟩
The normal rule in Haskell is that your program must supply a main function in module Main. When testing, it is often convenient to
change which function is the “main” one, and the -main-is flag allows
you to do so. The ⟨thing⟩ can be one of:
A lower-case identifier foo. GHC assumes that the main function is Main.foo.
A module name A. GHC assumes that the main function is A.main.
A qualified name A.foo. GHC assumes that the main function is A.foo.
So, try ghc -main-is Golf2 Golf2.hs -o Golf2 && ./Golf2.

How to correctly define your 'company' Prelude

I have decided to use my own Prelude for a larger project (containing some libraries and some executables). The Prelude doesn't export some partial functions and exports some common functions (i.e. from Control.Monad etc.). However, I am fighting with the way how to do it. I have tried:
use base-noprelude. Create Prelude.hs in module my-common-module.
Same as above, but in the my-common-module create My.Prelude instead. In every other module create a directory 'prelude', put it into hs-source-dirs cabal section, create a file prelude/Prelude.hs with import My.Prelude
The problem is that in 1) I cannot just run ghci, as I get conflicting base and my-common-module. In 2) ghci works, cabal repl somehow doesn't as it fails mysteriously with 'attempting to use module ‘Prelude’ (prelude/Prelude.hs) which is not loaded'. Additionally, base-noprelude doesn't seem to like ghcjs, which I want to use for part of the project (code sharing).
It seems to me the only way currently is to start each and every file with:
import Prelude ()
import My.Prelude
or
{-# LANGUAGE NoImplicitPrelude #-} -- or extensions: NoImplicitPrelude in .cabal
...
import My.Prelude
The 'extensions: NoImplicitPrelude' option seems to me best as it requires every file to import My.Prelude otherwise it won't work. Am I missing some obvious way that would achieve custom Prelude and at the same time work with cabal repl and ghcjs?
Update: base-noprelude works with GHCJS when I manually remove the reexport of GHC.Event.
Update: Ok, I spent some time with this and I should have spent more. It seems to me that 1) is the right way to go. cabal repl works (thanks Yuras), ghci must be loaded with ghci -hide-package base and works too.
I ended up with this setup that seems to work:
Create a special package my-prelude. This package exports the Prelude, can contain other modules, it can depend on base. You may need to use {-# LANGUAGE NoImplicitPrelude #-} in some modules to avoid circular dependencies. E.g. you may want to have some orphan instances defined and exported by your custom Prelude in separate files (e.g. Orphans.Lib_aeson), these files need the NoImplicitPrelude.
In your main project, libraries etc. change the dependencies in cabal from base to base-noprelude, my-prelude.
What works:
cabal repl
ghci/runghc works, but you have to start it with ghci -hide-package base; otherwise there will be conflict between base and my-prelude
What does not work:
cabal repl in the my-prelude package.

Module loading options in GHCi

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!

Resources