How to diagnose "Perhaps you need to add xxx to the build-depends in your .cabal file", when it is already in the cabal file? - haskell

I think the only interesting bits are my imports and my cabal file. Here are the imports and the demonstration of how I would use the problematic import (Database.CQL.IO.Log).
module FDS.Database.Cassandra where
import Prelude hiding(init)
import Database.CQL.IO as Client hiding(Logger)
import Database.CQL.IO.Log as CQLLog
import qualified Database.CQL.Protocol as CQL
import Numeric.Natural
import System.Logger (Logger)
cqlLogger :: Logger -> CQLLog.Logger
cqlLogger logger = undefined
However, I get the error:
src/FDS/Database/Cassandra.hs:7:1: error:
Could not load module `Database.CQL.IO.Log'
It is a member of the hidden package `cql-io-1.1.0'.
Perhaps you need to add `cql-io' to the build-depends in your .cabal file.
Use -v to see a list of the files searched for.
|
7 | import Database.CQL.IO.Log as CQLLog
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
But as we can see from the cabal file, it is there:
library
ghc-options: -Wall -Wtabs -Wincomplete-record-updates
default-extensions:
OverloadedStrings
exposed-modules:
FDS
, FDS.Config.Core
, FDS.Config.Dhall
, FDS.Data.Util
, FDS.Database.Cassandra
other-modules:
FDS.Data.Hobo.Defs
build-depends:
prelude
, base-noprelude ^>=4.12
, bytestring ^>=0.10.8.2
, conduit ^>=1.3.1
, containers ^>=0.6
, cql ^>=4.0.1
, cql-io ^>=1.1.0
One thing to note, I do have cql-io in my extra-deps in stack.yaml, as the latest version wasn't yet in LTS.
Q&A from Comments
Q Are there other components in your cabal file (e.g. executables, benchmarks, test suites)?
A Yes
Q Do they also use FDS.Database.Cassandra (but perhaps without depending on cql-io)?
A Not yet, but plan to later. So I haven't touched the other components yet.
Q Does the version of cql-io chosen by your build tool still export Database.CQL.IO.Log?
A It seems to do so.
Q What is the exact command you are running when you see that error?
A stack --nix build The only interesting bit that --nix is doing (AFAIK) is pulling in required system packages, e.g., OpenSSL.

The comments above were very insightful for the general case of the question (as posed); the answer being, sub-libraries that are recently supported by cabal may not have visibility: true declared.
But in my specific case, the answer is to look at the problematic library's re-exports. I could get around this issue because the cql-io authors re-exported Logger (..) and LogLevel(..) from the main library.
So that would allow me to write my code.
An even better answer that is very specific to my situation, as I was trying to use TinyLog, is that there is a library for that already ... here is the code from that library that demonstrates how to get around the issue (and solves the problem for me completely, as I now shouldn't have to write any code).
Here is the relevant excerpt:
module Database.CQL.IO.Tinylog (mkLogger) where
import Data.ByteString.Builder
import Data.ByteString.Lazy (ByteString)
import Database.CQL.IO (Logger (..), LogLevel (..))
import Database.CQL.IO.Hexdump
import qualified Data.ByteString.Lazy as L
import qualified System.Logger as Tiny
-- | Create a cql-io 'Logger' that delegates log messages to
-- the given tinylog 'Tiny.Logger'. Requests and responses are
-- logged on 'Tiny.Trace' level.
mkLogger :: Tiny.Logger -> Logger
mkLogger l = Logger
{ logMessage = tinylogMessage l
, logRequest = tinylogRequest l
, logResponse = tinylogResponse l
}
And here is how I adjusted my imports in the example above to confirm and get GHC happy (though I will scrap this now in favor of using cql-io-tinylog):
import Prelude hiding(init, log)
import Database.CQL.IO hiding(Logger)
import qualified Database.CQL.IO as CQLIO
import qualified Database.CQL.Protocol as CQL
import Numeric.Natural
import System.Logger hiding(defSettings)

Related

Cannot find module 'Text.HTML.TagSoup'

I have installed tagsoup with
cabal v1-install tagsoup
and verified the install with ghc-pkg list | grep tagsoup
However, in my very simple Haskell 8.6.5 program the statement
import Text.HTML.TagSoup
fails with cannot find module 'Text.HTML.TagSoup'
ghc -v is not useful
cabal new-install tagsoup fails with a ton of errors
import Network.HTTP.Conduit
import Text.HTML.TagSoup
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.Char8 as CL
main :: IO ()
main = do
lbs <- simpleHttp "https://wiki.haskell.org"
print $ show lbs
-- tagsoup code removed
For this kind of a single file use case, I'd recommend using a Stack script. If you add the following two lines to the top of your file:
#!/usr/bin/env stack
-- stack --resolver lts-13.27 script
You can then run stack filename.hs, which will:
Download GHC if necessary
Download and build all dependencies, based on your import list
Use runghc to run your program
More information:
How to Script
Get Started with Haskell

Finding explicit imports for ghc's -Wmissing-import-lists

GHC generates warnings when there are implicit imports (see below). The goal is to replace these with explicit imports. Is there an automated way to generated the list (instead of manually finding it in code)?
/Users/srid/code/slownews/backend/src/SlowNews/Main.hs:10:1: warning: [-Wmissing-import-lists]
The module ‘Control.Exception’ does not have an explicit import list
|
10 | import Control.Exception
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/Users/srid/code/slownews/backend/src/SlowNews/Main.hs:13:1: warning: [-Wmissing-import-lists]
The module ‘Control.Monad.IO.Class’ does not have an explicit import list
|
13 | import Control.Monad.IO.Class
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
GHC has a -ddump-minimal-imports flag which will do the trick.
There's an open pull request un importify tool which I'm working on. After this is done you will be able to convert implicit imports to explicit automatically:
https://github.com/serokell/importify/pull/82
The Haskell Tools project has some nice looking tooling for that. Apparently it works in Atom but I couldn't get it to work with atom or atom-beta on macOS. However, it does work at the command line. I have a simple example stack project set up. The Main.hs uses an explicit import list:
module Main where
import System.Environment
doMain = print =<< getEnvironment
main = doMain
BTW, I installed the Haskell Tools with:
$ stack install haskell-tools-daemon haskell-tools-cli fswatch
Then execute:
$ ht-refact -e 'ProjectOrganizeImports' .
Now git tells me that I have the following diff:
-import System.Environment
+import System.Environment (getEnvironment)
Check out the Haskell Tools website for an interactive example of how it should work in an editor. Looks like a very promising set of refactoring tools.

Error: "Failed to load interface for 'Data.Either.Utils'"

Does anyone know why this single, specific import statement is causing a problem? I'm using sandbox and cabal. My other imports work fine (Web.Scotty, Data.Text.Lazy, etc.). I'm running with "cabal exec runghc filename.hs". I don't have a cabal.config file, but I do have a cabal.sandbox.config file.
I'm attempting to use the forceEither function, which is in Data.Either.Utils. My import statements are normal as far as I can tell:
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Control.Monad.Trans (liftIO)
import Data.Aeson (object, (.=))
import Network.HTTP.Types.Status
import Data.Text.Lazy
import Data.Text.Lazy.IO
import Data.Either.Utils
import Data.Monoid (mconcat)
Message:
filename.hs:8:1: error:
Failed to load interface for ‘Data.Either.Utils’
Use -v to see a list of the files searched for.
Running with -v shows:
Using a sandbox located at
/Users/myuser/Desktop/mydirectory/myotherdirectory/.cabal-sandbox
/usr/local/bin/ghc --print-global-package-db
/usr/local/bin/runghc filename.hs
The Data.Either.Utils module is not part of "base" Haskell; it's part of the MissingH package, and that package seems to be .. ha ha .. missing!
I'm not too familiar with Cabal sandboxes (I use Stack), but presumably you can run:
cabal install MissingH
in your sandbox, and you should be good to go.
If that doesn't work, just copy the code for forceEither from MissingH:
forceEither :: Show e => Either e a -> a
forceEither (Left x) = error (show x)
forceEither (Right x) = x

Using `version` from Paths_* in a Yesod application

I am trying to write a GET handler in Yesod that returns the application version.
Here is the Haskell code for the handler:
{-# LANGUAGE OverloadedStrings #-}
module Handler.Version where
import qualified Data.Text as T
import Data.Version (showVersion)
import Import
import Paths_MyApp (version)
getVersionR :: Handler Value
getVersionR = return $ object
[ "version" .= T.pack (showVersion version) ]
I added an import in Application.hs:
import Handler.Version
and a line in routes:
/version VersionR GET
but I am getting the following error when running cabal install:
.../MyApp/dist/build/libHSMyApp-0.1.0.a(Version.o):(.text+0xda5):
undefined reference to `MyAppszm0zi1zi0_PathszuMyApp_version1_closure'
I suspect something is missing in my .cabal file, but I'm not sure what. I added Handler.Version to the exposed-modules section, but am wondering if I need to somehow mention the Paths_* file.
Solved:
I added
Paths_MyApp
to the exposed_modules section of the .cabal file. It now compiles correctly.

Could not find module, it is a member of the hidden package haskell98

When I try to compile a simple source file with import IO or import Random, the build fails with an error message like this:
Could not find module 'IO'
It is a member of the hidden package 'haskell98-2.0.0.1'
Use -v to see a list of the files searched for
The module names changed at some point. You probably want import System.IO and import System.Random instead.
Here is the module hierarchy for the standard libraries in GHC 7.6.1.

Resources