Using `version` from Paths_* in a Yesod application - haskell

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.

Related

Why is stack not auto detecting my module?

I am trying to write a script that uses Diagrams but the stack package detection feature is confusing me. I have two files and when the support module imports SVGFonts stack doesn't add it to the list of modules that are found. Instead, it's hidden. When the import is in the main file, however, it downloads it and finds it for the build just fine.
Main.hs
-- stack --resolver lts-19.0 script
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
import Diagrams.Prelude
import MyMod (val)
import Diagrams.Backend.SVG
main = print val
MyMod.hs
module MyMod where
import Diagrams.Backend.SVG
val = 1
And I am getting this error
Could not load module ‘Diagrams.Backend.SVG’
It is a member of the hidden package ‘diagrams-svg-1.4.3.1’.
You can run ‘:set -package diagrams-svg’ to expose it.
(Note: this unloads all the modules in the current scope.)
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
3 | import Diagrams.Backend.SVG (loadFont)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
How can I get stack to automatically find that I need SVGFonts and import it properly without adding the import to my main file?

Haskell Crypto Hash SHA256 replit failure

I'm trying to hash text using Crypto.Hash modules on replit.com, I don't know how to resolve this failure: Could not find module ‘Crypto.Hash’
Code:
import Crypto.Hash (hashWith, SHA256(..))
import Data.ByteString (ByteString)
main = do
putStrLn "Hello"
putStrLn "World"
hashWith SHA256 ("hello" :: ByteString)
I will be very grateful for your help!!!
It looks like replit.com is Nix based, and it uses a replit.nix configuration file to configure the Nix environment, including loaded GHC packages.
So, one way to get this working is to edit the replit.nix file. (By default, it won't be shown in the "Files" tab, but you can click the vertical "..." in the top-right corner and select "Show hidden files" to view it.) Modify it to look something like:
{ pkgs }: {
deps = [
(pkgs.haskellPackages.ghcWithPackages (pkgs: [
pkgs.cryptonite
]))
pkgs.haskell-language-server
];
}
Now, when you run the source, it should reconfigure the Nix environment and load the required cryptonite package. You may need to modify your code slightly, too, as it uses an OverloadedStrings extension, and hashWith isn't an IO action. I got the following Main.hs to work:
{-# LANGUAGE OverloadedStrings #-}
import Crypto.Hash (hashWith, SHA256(..))
import Data.ByteString (ByteString)
main = do
print $ hashWith SHA256 ("hello" :: ByteString)

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?

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)

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

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