let say I have a project which is just a bunch of Haskell modules with exercises. I'd like to provide a .ghci
which automatically imports all modules into ghci
scope. The problem is, I can not run import
nor :m Module.Name
within .ghci
file.
Clearly cabal repl
is reading the .ghci
file because options like the prompt are readed. Also it loads modules correctly, but it doesn't bring them into scope (only one gets imported). If I try to add import OtherModule
to .ghci
file, then I get the error
module is member of hidden package fail-ghci
Perhaps you need to add ‘fail-ghci’ to the build-depends in your .cabal file.
But I can't add fail-ghci to the cabal file, because the library can't depend on itself!!
To reproduce. Create a simple cabal project. For example:
src
|- Module1.hs # include dummy function func1 :: Int
|- Module2.hs # include dummy function func2 :: Int
fail-ghci.cabal
.ghci
The content of fail-ghci.cabal
is
name: fail-ghci
version: 0.1.0.0
license: BSD3
license-file: LICENSE
build-type: Simple
library
exposed-modules:
Module1
, Module2
hs-source-dirs:
src
build-depends:
base >=4.7 && <5
default-language: Haskell2010
If you set .ghci
as
:set prompt "> " -- Set this option to ensure .ghci is readed by cabal repl
It will work fine and will bring Module1.hs
into scope, so func1
is available. But Module2.hs
wont be in the scope, If I want to use it I'd need to execute import Module2
or equivalent.
Now, I'd like this to happen automatically when running cabal repl
because my project has many modules. The obvious (to me) choice is to modify .ghci
as
:set prompt "> " -- Set this option to ensure .ghci is readed by cabal repl
import Module2 -- Equivalent :m Module2
But the ghci is unable to import the module, despite of that command woring correctly within ghci. What's the correct configuration to do this?
CodePudding user response:
I suppose the problem is simply that cabal executes the commands in your .ghci
file before it loads the current project.
Indeed when I cabal repl
in a similar project, the startup output is:
Build profile: -w ghc-9.0.2 -O1
In order, the following will be built (use -v for more details):
- fail-ghci-0.1.0.0 (first run)
Preprocessing library for fail-ghci-0.1.0.0..
GHCi, version 9.0.2: https://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /tmp/scratch/.ghci
[1 of 2] Compiling Module1 ( src/Module1.hs, interpreted )
[2 of 2] Compiling Module2 ( src/Module2.hs, interpreted )
Ok, two modules loaded.
ghci>
My guess would be that this is probably because cabal repl
starts a ghci session (which loads the .ghci
file during startup) and then uses its API to load the project environment. (I was able to confirm that a .ghci
file can import modules from packages that are fully installed, rather than from a current project being cabal repl
d)
I don't know of any way to automatically execute commands after the project has been loaded. But you can have your .ghci
file define a shortcut command that will import all the modules you want. That way you have at least have a single quick command to execute once you're in the ghci shell, instead of manually importing everything. Something like this:
:def loadall (const . pure) ":m *Module1 *Module2"
-- or
:def loadall (const . pure) "import Module1 Module2"
-- or etc
Then you can just enter :loadall
at the ghci prompt to get your modules imported.