
On Thu, 2013-04-04 at 15:46 +0100, Rob Stewart wrote:
Hi Duncan, Edsko.
I'd like to know where I should most appropriately submit a bug report, or indeed whether the behaviour that I am experiencing is a bug or a user misuse of cabal.
It's a consequence of a misunderstanding of how package names affect types and how different cabal constructs give you different package names.
I have packaged up a very simple send/receive example into a cabalised archive. In there is a README that describes the problem succinctly, though I will repeat here for convenience. It appears to be weirdness with main-is and hs-source-dirs. In the .cabal file, there are three executables of the same Receiver.hs file - a receiver of a CH message. One appears to be defined in such a way that the CH primitives `match` and `expect` are *not* receiving the message types that are being sent by Sender.hs.
The problem is that your three programs are using different types. ch-receiver-1 and ch-receiver-2 use the type cabal-with-ch-executables-1.0:Bar.Baz.Types.Msg while ch-receiver-3 uses the type Bar.Baz.Types.Msg Those are the fully-qualified names of those types and they are different, so they are different types, so have different Typeable fingerprints and so the `expect` does not match them. So as you can see, the fully qualified name of a type includes its package id, and in the first case it has the package name cabal-with-ch-executables-1.0 while in the second case it is the "home" package, which has no name (or if you like, it's called ""). Code in a library has fully qualified names that include the package name. Code in a top level executable is in the "home" package. The way you've constructed your three programs, the first two put the module in a library and the third puts it in the top level executable, so according to ghc it really is a different module. So lets look at your cabal file:
library default-language: Haskell2010 exposed-modules: Bar.Baz.Types , Bar.Baz.Identify build-depends: base >= 4 && < 5 , binary >= 0.6.3.0 , bytestring >= 0.9.2 , distributed-process >= 0.4.2 , network , network-transport , network-transport-tcp hs-source-dirs: src GHC-Options: -Wall
-- Works Executable ch-receiver-1 default-language: Haskell2010 main-is: Receiver.hs build-depends: base , distributed-process , network-transport-tcp , network-transport , cabal-with-ch-executables hs-source-dirs: examples ghc-options: -Wall
-- Works Executable ch-receiver-2 default-language: Haskell2010 main-is: Receiver.hs build-depends: base , distributed-process , network-transport-tcp , network-transport , cabal-with-ch-executables hs-source-dirs: src/Bar/Baz ghc-options: -Wall
-- Doesn't work Executable ch-receiver-3 default-language: Haskell2010 main-is: Bar/Baz/Receiver.hs build-depends: base , distributed-process , network-transport-tcp , network-transport , cabal-with-ch-executables
-- I don't understand why these below are now needed?? , binary >= 0.6.3.0 , bytestring >= 0.9.2 , distributed-process >= 0.4.2 , network , network-transport , network-transport-tcp hs-source-dirs: src ghc-options: -Wall
So you have the first two executables depending on the library and they pick up their Bar.Baz.Types module from the library. Your third executable also depends on the library but the way you have the sources organised means that you're getting the modules from the source files and not from the library. This is because you're using the hs-source-dirs as src, which is where the modules for the library live. ghc will always pick local source files over modules from packages. This is also why you needed those extra dependencies, your executable is including those modules directly (you'll notice they're recompiled for the 3rd exe). The solution is that when you want to have an exe in a package depend on a lib in the same package, you need to separate the src dirs, as you did with the first one (hs-source-dirs: examples). Clear as mud? What would be good is if cabal would warn when the same module can be found both in a local lib that we depend on, and as a source file, because that's probably a mistake. It might also be good if we could tell ghc where to get the modules from explicitly, rather than rely on its behaviour about preferring src modules to package modules. Duncan