cabal-dev install Happstack-server how - haskell

here is what I did:
makdir happstack_01
cabal-dev install happstack-server
write the typical helloworld.hs with "import Happstack.Server (nullConf, simpleHTTP, toResponse, ok)"
ghc -threaded HelloWorld.hs -o helloworld
and I got:
Could not find module `Happstack.Server'
This is so obvious wrong. But what I am more surprised is that no tutorial on google for simple thing as this.
Any intuition would be awesome!

This is a set of instructions for a very bare-bones, Cabalized, and sandboxed build.
$ mkdir happstack01 && cd happstack01/
$ cabal init .
$ <CR><CR><CR><CR><CR><CR><CR><CR><CR> 1 <CR><CR><CR>
$ mkdir src
$ touch src/Main.hs
$ vi happstack-01.cabal
In happstack01.cabal
...
library
exposed-modules:
Main
build-depends: base >=4.6 && <4.7
, happstack-server
hs-source-dirs: src
default-language: Haskell2010
Then
$ cabal sandbox init
$ cabal install --only-dependencies
$ vi src/Main.hs
In src/Main.hs
import Happstack.Server
main :: IO ()
main = simpleHTTP nullConf $ return "Hello sandbox!"
Get some coffee while the sandbox builds.
$ cabal repl
> main
After this I usually add an executable entry to the Cabal file and begin to build the server from that.

Since you wanted a small tutorial, I am writing up how I just got it to work. I used cabal instead of cabal-dev though (if you care, let me know and I can play around a bit more)....
> cabal install happstack-server
> mkdir sample
> cd sample
Then I created the file sample.hs
import Happstack.Server
main = simpleHTTP nullConf $ return "hello, world!"
and I compiled it
> ghc sample.hs
(This is where you seem to be having problems finding the library.... You might want to check if ~/.ghc//package.conf.d/happstack-server-7.3.1-.conf and ~/.cabal/packages/hackage.haskell.org/happstack-server/ exist to verify the download)
Then run the server
./sample
and verify that it works using curl
> curl http://127.0.0.1:8000
This should respond with
hello, world!

ok I figured this out. GHC will not regonized local sanboxed libs. at least my GHC --version 7.6.3 does not. So I will have to cabalise my project in order to make sandboxed libs work.

Related

How to work together with cabal-3 and ghc (ghc-pkg, too)?

With the release of cabal-3, the packages from Hackage are installed in a new location that the compiler ghc and ghc-pkg know nothing about.
In other words, packages are installed but not registered for ghc. Ghci, ghc, ghc-pkg cannot work.
For example,
cabal install safe --lib
Create file t1.hs
import Safe
t1 = tailMay [1,2,3]
Let's try:
> ghci t1.hs
GHCi, version 8.10.2: https://www.haskell.org/ghc/:? for help
[1 of 1] Compiling Main (t1.hs, interpreted)
t1.hs: 1: 1: error:
Could not find module `Safe '
Use -v (or `: set -v` in ghci) to see a list of the files searched for.
|
1 | import Safe
| ^^^^^^^^^^^
Failed, no modules loaded.
This bug is described here
https://github.com/haskell/cabal/issues/6262
and here
https://gitlab.haskell.org/ghc/ghc/-/issues/17341
I use as a temporary solution setting a system variable
GHC_PACKAGE_PATH=C:\Users\me\AppData\Roaming\cabal\store\ghc-8.10.2\package.db;
(Windwos 10, haskell-dev by chocolatey)
via
On Windows, packages installed with cabal seem to be unavailable in ghc/ghci
but with updates I will have to manually change this system variable.
Are there any more elegant solutions to this problem?
P.S. Unfortunately, this solution (via GHC's environment variable GHC_PACKAGE_PATH) is incompatible with Cabal :(
https://github.com/haskell/cabal/issues/1944
One way to achieve this is to use the --env flag to make the libraries available to GHC whenever you are in the current directory:
~ $ mkdir /tmp/foo
~ $ cd /tmp/foo
/tmp/foo $ cabal install safe --lib --env .
Resolving dependencies...
Build profile: -w ghc-8.8.3 -O1
In order, the following will be built (use -v for more details):
- safe-0.3.19 (lib) (requires build)
Configuring library for safe-0.3.19..
Preprocessing library for safe-0.3.19..
Building library for safe-0.3.19..
…
> Installing library in /home/jojo/.cabal/store/ghc-8.8.3/incoming/new-4056/home/jojo/.cabal/store/ghc-8.8.3/safe-0.3.19-92fbaef88124b4508ce447f6245bc793f7a1748247ae68d10e449150df1069af/lib
t1.hs
/tmp/foo $ cat > t1.hs
import Safe
t1 = tailMay [1,2,3]
/tmp/foo $ ls -a
. .. .ghc.environment.x86_64-linux-8.8.3 t1.hs
/tmp/foo $ ghci t1.hs
GHCi, version 8.8.3: https://www.haskell.org/ghc/ :? for help
Loaded package environment from /tmp/foo/.ghc.environment.x86_64-linux-8.8.3
[1 of 1] Compiling Main ( t1.hs, interpreted )
Ok, one module loaded.
*Main>
Note that you probably shouldn’t do this in a directory where you actually have a foo.cabal file. See the documentation of cabal v2-install for details.
Working with GHC_ENVIRONMENT is better:
setx GHC_ENVIRONMENT C:\Users\me\.ghc\x86_64-mingw32-8.10.2\environments\default
it helps for ghc and ghci.
After, in C:\Users\me\AppData\Roaming\cabal\config we should add
package-db: C:\Users\me\AppData\Roaming\cabal\store\ghc-8.10.2\package.db
it helps for cabal.
Unfortunately, ghc-pkg still has problem and works with such flag:
ghc-pkg list --user-package-db="C:\Users\me\AppData\Roaming\cabal\store\ghc-8.10.2\package.db"
For Linux the steps are similar.

How to install and import a library in haskell?

In official tutorial Haskell in 5 steps, an example imports a library:
import Control.Parallel
Then I use ghc to compile:
ghc parallel.hs -o parallel -O2 --make -threaded -rtsopts
just as the tutorial tells me to do. (My filename is parallel.hs) But I got:
parallel.hs:1:1: error:
Could not find module ‘Control.Parallel’
Use -v to see a list of the files searched for.
|
1 | import Control.Parallel
| ^^^^^^^^^^^^^^^^^^^^^^^
Then I stackoverflowed it and find this question. So I:
cabal new-install parallel --lib
And get:
Resolving dependencies...
Up to date
Then I compiled it again, but got the same error.
How to solve this? Did I miss any command line arguments?
Well, after cabal install parallel, the library is imported, the program is compiled successfully, and runs as expected.
I'll refer to documentations of cabal about the difference between install and new-install
As #Lorenzo noted, cabal install works fine. With cabal new-install you should have seen a warning that you forgot --lib since parallel does not include an executable and libraries must be explicitly installed via --lib. The full set of functional commands are:
cd $(mktemp -d)
cabal update && cabal new-install --lib parallel
cat <<EOF > parallel.hs
module P where
import Control.Parallel
EOF
ghc -c parallel.hs
ls parallel.o parallel.hi
Yielding:
% cd $(mktemp -d)
% cabal update && cabal new-install --lib parallel
... snipped output ...
% cat <<EOF > parallel.hs
module P where
import Control.Parallel
EOF
% ghc -c parallel.hs
Loaded package environment from /home/tommd/.ghc/x86_64-linux-8.6.4/environments/default
% ls parallel.o parallel.hi
parallel.hi parallel.o

Cabal Vs runhaskell, when to use?

In haskell build system, Cabal as well as runhaskell has got almost same set of sub-commands, configure, build. For runhaskell, it is:
runhaskell Setup.hs configure
runhaskell Setup.hs build
...whereas for cabal it is:
cabal build
cabal configure
So, when should I use which command? Do both the commands have same functionality?
Can I run runhaskell without sudo access, because I see runhaskell makes entries inside /opt/ghc/7.8.4/lib whereas cabal works in sudo/non-sudo mode?
cabal and runhaskell serve entirely different purpose.
runhaskell is used for executing Haskell programs without
having the need to compile them. You can place this on the top of an Haskell file: #!/usr/bin/env runhaskell and give it the scripting ability. The cabal is a package manager and a build system
for Haskell.
Also cabal and runhaskell don't share their sub-commands like
configure, build, install etc.
i saw in this link bob.ippoli.to/archives/2013/01/11/getting-started-with-haskell, two commands being used... runhaskell Setup.hs configure && runhaskell Setup.hs build
Usually Setup.hs has the following code when generated from cabal init:
import Distribution.Simple
main = defaultMain
Now if you see the implementation of defaultMain:
defaultMain :: IO ()
defaultMain = getArgs >>= defaultMainHelper simpleUserHooks
So what you are passing is actually command line arguments which can be anything. In fact you can test that yourself:
$ runhaskell Setup.hs invalid_argument
unrecognised command: invalid_argument (try --help)
runhaskell doesn’t have any subcommands:
$ runhaskell --help
Usage: runghc [runghc flags] [GHC flags] module [program args]
It takes a path to a Haskell source file and executes it right away. So you should use it when all you want is to run some Haskell code you have. Of course, you can use runhaskell without superuser access; I doubt it creates anything in /opt.
Cabal is a build-system for Haskell projects, its purpose is transforming Haskell sources into binaries.

ghc-mod does not use my cabal sandbox. why?

runghc -package-db=.cabal-sandbox/.cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d hellowai.hs
Works perfect for me.
Similarly, with
ghci -package-db=.cabal-sandbox/.cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d
I am also able to import my cabal-sandbox-installed Wai package in ghci with no issue at all.
But when I ask ghc-mod to validate my haskell source code, via
ghc-mod check --boundary="" -g -package-db=.cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d hellowai.hs
hellowai.hs:4:8:Could not find module ‘Network.Wai.Handler.Warp’Use -v to see a list of the files searched for.
hellowai.hs:3:8:Could not find module ‘Network.HTTP.Types’Perhaps you meant Network.HTTP.Base (from HTTP-4000.2.19) Network.HTTP.Base (needs flag -package HTTP-4000.2.10) Network.HTTP.Headers (needs flag -package HTTP-4000.2.10)Use -v to see a list of the files searched for.
hellowai.hs:2:8:Could not find module ‘Network.Wai’Perhaps you meant Network.BSD (needs flag -package network-2.4.2.3) Network.URI (needs flag -package network-2.4.2.3) Network.TCP (needs flag -package HTTP-4000.2.10)Use -v to see a list of the files searched for.
It is unable to find my cabal sandbox installed module. Why is that so?
Do you have a cabal.sandbox.config file? And are you using a .cabal file for your project?
If you have both of these you should be able to use ghc-mod check ... and it will just work.
Another advantage of using a .cabal file is that you can use cabal repl to invoke ghci and cabal run to invoke runhaskell with the correct command line options.
Update
Here is a recipe you can try out to see when ghc-mod can find your cabal sandbox. Perhaps this can help you determine what's different with your set up.
Start in a clean directory:
$ mkdir foo
$ cd foo
$ cabal sandbox init
$ cabal get split
$ cd split-0.2.2
$ cabal sandbox init --sandbox=../.cabal-sandbox
Edit around line 55 of split.cabal to add heredoc as a dependency.
Edit src/Data/List/Split.hs to use the module Text.Heredoc:
{-# LANGUAGE QuasiQuotes #-}
...
import Text.Heredoc
...
foo :: String
foo = [here|this is a test|]
Make sure heredoc is installed:
$ cabal install --only-dependencies
Finally this should work:
$ ghc-mod check ./src/Data/List/Split.hs
And it will still work if you cd into a sub-directory:
$ cd src
$ ghc-mod check ./Data/List/Split.hs
However, ghc-mod won't work if you move away split.cabal:
(back at the top level directory)
$ mv split.cabal split.cabal-old
$ ghc-mod check ./src/Data/List/Split.hs
In this case I created the sandbox in a parent directory of our working directory, but things should also work if the initial sandbox was created like this:
$ mkdir foo
$ cd foo
$ mkdir sandbox-dir
$ cd sandbox-dir
$ cabal sandbox init
$ cd ..
$ cabal get split
$ cd split-0.2.2
$ cabal sandbox init --sandbox=../sandbox-dir/.cabal-sandbox

Including data files in cabal builds

I have a package with the following structure (okay, this is greatly simplified, but...)
app/
src/
Main.hs
data/
data.txt
app.cabal
Paths_app.hs
Setup.hs
In Paths_app.hs I have:
module Paths_app where
getDataFileName :: FilePath -> IO FilePath
getDataFileName = return
and in Main.hs I have:
module Main where
import Paths_app
main = do
file <- getDataFileName "data/data.txt"
data <- readFile file
putStrLn $ "Your data is: " ++ data
the relevant parts of my app.cabal file look like this:
name: app
version: 1.0
build-type: Simple
data-files: data/data.txt
executable foo
build-depends: base, haskell98
main-is: Main.hs
hs-source-dirs: src
This builds fine (using cabal configure followed by cabal install) but the executable complains that it can't find the data.txt file. I've tried replacing the line
file <- getDataFileName "data/data.txt"
with
file <- getDataFileName "data.txt"
but the same thing occurs. Is there something obvious I'm doing wrong?
I've tried to reproduce it, but it works fine for me.
In the setup you describe, I had to drop the dependency on haskell98 as both base and haskell98 were providing Prelude. Furthermore, the file Main wouldn't compile as it used the keyword data as a variable name, so I renamed the variable to dat. But then it worked just fine.
Some info on my setup:
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.4.1
$ cabal --version
cabal-install version 0.13.3
using version 1.14.0 of the Cabal library
$ ls ~/.cabal/bin/
... foo ...
$ ls ~/.cabal/share/app-1.0/data/
data.txt
The problem was that I was building on a Windows system, and when I used the filename returned by getDataFileName to load data into my program, I wasn't escaping the backslashes.

Resources