cabal icon indicating copy to clipboard operation
cabal copied to clipboard

imported modules in cabal repl with multiple home units - very broken (?)

Open prez opened this issue 1 year ago • 4 comments

I'm just an amateur Haskell user (neither beginner nor expert), and wanted to try the new multi-repl support in cabal 3.12. Below is a description of my frustration and some unexpected behavior I encountered while doing so, complete with a minimal reproducer.


In ~/.cabal/config: multi-repl: True

Project structure:

a $ tree
.
├── a.cabal
├── src
│   └── Main.hs
└── test
    └── Spec.hs

3 directories, 3 files

contents of a.cabal:

cabal-version:        3.12
name:                 a
version:              0.1.0.0
build-type:           Simple

common depends
    build-depends:    , base ^>=4.20.0.0
    default-language: Haskell2010

executable a
    import:           depends
    main-is:          Main.hs
    ghc-options:      -main-is Main
    hs-source-dirs:   src

test-suite a-test
    import:           depends
    main-is:          Spec.hs
    ghc-options:      -main-is Spec
    hs-source-dirs:   test
    build-depends:    QuickCheck

contents of src/Main.hs:

module Main where

eight :: Int
eight = 8

main :: IO ()
main = pure ()

contents of test/Spec.hs:

module Spec where

import Test.QuickCheck

nine :: Int
nine = 9

main :: IO ()
main = pure ()

making sure both components work normally:

a $ cabal repl exe:a
Build profile: -w ghc-9.10.1 -O1
In order, the following will be built (use -v for more details):
 - a-0.1.0.0 (interactive) (exe:a) (first run)
Preprocessing executable 'a' for a-0.1.0.0...
GHCi, version 9.10.1: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/anon/.ghci
[1 of 2] Compiling Main             ( src/Main.hs, interpreted )
Ok, one module loaded.
ghci> ei
eight   either
ghci> eight
8
ghci> 
Leaving GHCi.
a $ cabal repl test:a-test
Build profile: -w ghc-9.10.1 -O1
In order, the following will be built (use -v for more details):
 - a-0.1.0.0 (interactive) (test:a-test) (first run)
Configuring test suite 'a-test' for a-0.1.0.0...
Preprocessing test suite 'a-test' for a-0.1.0.0...
GHCi, version 9.10.1: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/anon/.ghci
[1 of 2] Compiling Spec             ( test/Spec.hs, interpreted )
Ok, one module loaded.
ghci> nine 
9
ghci> generate arbitrary :: IO Int
26
ghci> 
Leaving GHCi.
  • eight and nine are both in scope, respectively, as one would expect.

trying multi-repl all target

a $ cabal repl all
Build profile: -w ghc-9.10.1 -O1
In order, the following will be built (use -v for more details):
 - a-0.1.0.0 (interactive) (exe:a) (first run)
Preprocessing executable 'a' for a-0.1.0.0...
GHCi, version 9.10.1: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/anon/.ghci
[1 of 2] Compiling Main             ( src/Main.hs, interpreted )
Ok, one module loaded.
ghci> ei
eight   either
ghci> eight
8
ghci> nine
<interactive>:2:1: error: [GHC-88464]
    Variable not in scope: nine

ghci> 
Leaving GHCi.
  • Not looking good. It does have eight, but not nine.

trying to specificy both units explicitly:

a $ cabal repl exe:a test:a-test
Build profile: -w ghc-9.10.1 -O1
In order, the following will be built (use -v for more details):
 - a-0.1.0.0 (interactive) (exe:a) (first run)
 - a-0.1.0.0 (interactive) (test:a-test) (first run)
Configuring executable 'a' for a-0.1.0.0...
Preprocessing test suite 'a-test' for a-0.1.0.0...
Preprocessing executable 'a' for a-0.1.0.0...
GHCi, version 9.10.1: https://www.haskell.org/ghc/  :? for help
Command is not supported (yet) in multi-mode
Command is not supported (yet) in multi-mode
Command is not supported (yet) in multi-mode
Loaded GHCi configuration from /home/anon/.ghci
[1 of 4] Compiling Main             ( /home/anon/tmp/a/src/Main.hs, interpreted )[a-0.1.0.0-inplace-a]
[2 of 4] Compiling Spec             ( /home/anon/tmp/a/test/Spec.hs, interpreted )[a-0.1.0.0-inplace-a-test]
Ok, two modules loaded.
ghci> eight
<interactive>:1:1: error: [GHC-88464]
    Variable not in scope: eight
    Suggested fix:
      Perhaps use data constructor ‘Right’ (imported from Prelude)

ghci> nine
<interactive>:2:1: error: [GHC-88464]
    Variable not in scope: nine

ghci> 
  • ... Huh? Neither of the definitions are in scope. The output also looks different from the previous cabal incantation. Notice also the weird errors about some "Command" that is not supported in multi-mode (not even -v3 prints anything about them). My ~/.ghci happens to have exactly three "commands" in it, all of them copied from the haskellwiki and similar to :def hg \x -> return $ ":!hoogle \"" ++ x ++ "\""...

Even disregarding the obvious inconsistency, I don't think this is how it should behave? I was expecting it to just bring the definitions from both main-is/ghc-options: -main-is into scope (aside: why are both of those needed? This is not intuitive).

And another aside: here we just have two Main modules, but this is of course not representative of a real project. There you have to either import all of your modules by hand in the repl if you want to do repl-driven development, or import them into the Main module and live with an unused import warning for that file. There should really be a way to issue a sequence of commands to cabal repl (including loading / importing modules, IIRC there was one but it does not work because it runs before the modules are compiled and thus has no access to them)...

prez avatar Jul 24 '24 20:07 prez

Seems like things are mostly working as expected here.

  1. When you write cabal repl all you are not loading both units (you need --enable-tests as well to make all mean that).
  2. GHCi is not fully extended yet to support multiple units, only the basic GHCi commands are supported. This explains the "Command is not supported (yet) in multi-mode" errors. The "context" is the context of the last loaded unit.

It's not clear to me why neither eight or nine is in scope when using the multi-repl but I'm not sure it's worth investigating whilst it isn't consistent about why package ends up providing the final context.

It would be good to extend GHCi to work better with multiple units but that requires someone to perform or fund the work.

mpickering avatar Jul 29 '24 14:07 mpickering

Seems like things are mostly working as expected here.

I really appreciate your effort in implementing this feature, however I cannot agree with this.

The behaviour of this feature is currently very surprising (you said it yourself: It's not clear why neither eight or nine is in scope) - and that's clearly a bug. I understand that bringing this to a polished state requires work and funding, but could we at least agree on removing the "question" label and admitting that a multi-repl without repl functionality (such as definitions being in scope) is of rather dubious utility?

prez avatar Aug 04 '24 23:08 prez

I apologize for my confusion with the labels. I have removed the user-question label.

ulysses4ever avatar Aug 05 '24 00:08 ulysses4ever

We just merged a PR which significantly improves GHCi with multi repl: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/14231

In short, your use-case will work as you expect it, as well as all GHCi commands, and the GHCi debugger, which has been patched to work across home units.

We are talking about this during HiW 2025, and we will publish a blog post soon ™ .

fendor avatar Jun 03 '25 12:06 fendor