Can older Cabal or Haskell projects be run on newer versions of Cabal and Haskell? - haskell

I'm trying to build my project and I'm running into a really strange problem. I got my friend to install Haskell with Chocolatey and when he goes to compile my project with cabal build and cabal run project he runs into the following error that I just don't have:
Expr.hs:103:1: error:
Type applications in patterns are not yet supported
|
103 | evalVal env val #(HInteger _) = return $ val
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I assumed that the cabal file would take care of dependencies but obviously not. A cursory search as well proves fruitless because I can't even find another instance of someone having the same error.
I'm not sure if the problem is due to him being on ghc 9.0.1 and cabal 3.4 and I'm on ghc 8.8.3 and cabal 3.2 or if it's due to different operating systems, his being Windows and I OSX.
My worry is that if I upgrade my ghc and cabal versions then I will run into this error and I'll have to reinstall everything which was messy and difficult the first time

It turns out that was a change in GHC 9.0: Whitespace-sensitive !, ~, #, and $
it's the second point there:
f # x = y
Before: value binding that binds both f and x to y using an as-pattern
After: infix function named (#)
To restore the old behavior, remove the leading and trailing whitespace around #, like so:
f#x = x
So if you change it to
evalVal env val#(HInteger _) = return $ val
it should work for both compilers

Related

Building the Spock tutorial example fails

I wanted to get going with Haskell a little bit and therefore took a look at the Spock framework. To start clean, I uninstalled everything Haskell related from my Arch Linux machine and installed ghcup, Cabal and Stack using the install scripts from their respective websites.
Now I want to follow Spock's Tutorial. Trying to install Spock globally with cabal install Spock as suggested gives me an error (abbreviated):
src/Web/Spock/Internal/Wire.hs:43:1: error:
Could not find module ‘Web.Routing.AbstractRouter’
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
|
43 | import Web.Routing.AbstractRouter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cabal: Failed to build Spock-0.9.0.1. See the build log above for details.
I already found a question on reddit on the topic, but the solution does not apply because I'm not trying to use a specific version of the libraries as implied.
So I try to follow along and build only locally.
But when I reach the point where it says stack build --fast --pedantic, the build plan can not be constructed and Stack suggests to add another dependency, stm-containers. Doing so, I am presented with two additional suggestions for focus and primitive. When I add these, the plan fails again, this time without a simple solution:
In the dependencies for primitive-0.6.4.0:
base-4.13.0.0 from stack configuration does not match >=4.5 && <4.13 (latest matching version is 4.12.0.0)
needed due to Spock-example-0.1.0.0 -> primitive-0.6.4.0
I can do a little thing with Haskell, but with the build system(s), I am way out of my comfort zone. Help and hints appreciated. Oh, and all versions of course are the latest by the time of this post.
Due to incompatible versions of dependencies, Spock won't build with GHC 8.8 and above. A similar problem is described in Spock issue #149, though I'm not fully sure it is exactly the same incompatibility. The error you got from Stack hints at that, as base-4.13.0.0 is the version of base that is bundled with GHC 8.8. cabal-install failed in a more obscure way because, upon noting the incompatibility, it tries to solve the dependencies using older versions of Spock, eventually picking 0.9.0.1, attempting and, thanks to a missing version upper bound for the reroute dependency, failing to build it.
(Shortly after this answer was posted, the missing upper bound was retrofitted to the old Spock version, so attempting to reproduce the problem now will lead to an easier to understand failure.)
Casting the tutorial aside, the most straightforward way to use Spock given those complications is probably through cabal-install 3+. Begin by using ghcup to switch to GHC 8.6.5:
$ ghcup install 8.6.5
$ ghcup set 8.6.5
Then, create a blank project with cabal-install:
$ mkdir myproject
$ cd myproject
$ cabal init
Add Spock to the build-depends section of myproject.cabal:
build-depends: base >=4.12 && <4.13
, Spock == 0.13.*
Finally, you can run:
$ cabal build
Which will install Spock and its dependencies before building the project. (Note that you generally don't need to use cabal install to install libraries with cabal-install 3.)
It is presumably possible to make it work with Stack as well, by changing to the lts-14.27 resolver (the latest one that uses GHC 8.6.5), tracking down all dependency versions that need to be overriden (as you had began to do) and manually adding them to the extra-deps of stack.yaml.

Duplicate packages in Haskell environment?

I put this in a file (see bottom) and got the following error when loading it in ghci (i.e. start ghci then :l file):
7:13: error:
• Couldn't match expected type ‘network-uri-2.6.1.0#network-uri-2.6.1.0-7BN1tbB3iHQ2XgvmqLAYph:Network.URI.URI’
with actual type ‘Network.URI.URI’
NB: ‘Network.URI.URI’
is defined in ‘Network.URI’
in package ‘network-uri-2.6.1.0#network-uri-2.6.1.0-80FpvaNUTSDFCPv0sSze40’
‘network-uri-2.6.1.0#network-uri-2.6.1.0-7BN1tbB3iHQ2XgvmqLAYph:Network.URI.URI’
is defined in ‘Network.URI’
in package ‘network-uri-2.6.1.0#network-uri-2.6.1.0-7BN1tbB3iHQ2XgvmqLAYph’
Have I somehow installed two slightly different versions of network-uri, or what is this? How do I resolve it?
I've hardly used cabal but tried cabal install --reinstall network-uri, went fine but problem persists.
File contents:
import Network.HTTP
import Network.URI (parseURI)
import Data.Maybe (fromJust)
myRequestURL = "http://www.virginia.edu/cgi-local/ldapweb"
myRequest :: String -> Request_String
myRequest query = Request {
rqURI = fromJust $ parseURI myRequestURL
, rqMethod = POST
, rqHeaders = [ mkHeader HdrContentType "text/html"
, mkHeader HdrContentLength $ show $ length body ]
, rqBody = body
}
where body = "whitepages=" ++ query
main :: IO ()
main = do
response <- simpleHTTP $ myRequest "poon"
putStrLn ""
EDIT Re-installed haskell-platform. After this, ghc-pkg list reports all packages to be under (?) /usr/lib/ghc/package.conf.d, and the program I tried to copy loads just fine.
EDIT 2 After running cabal install some-pkg, ghc-pkg list reports that the newly installed stuff is in another directory. Indeed, ~/.cabal/config specifies install dirs for user, as well as install dirs for global. How is all this supposed to be managed properly?
GHC understands the concept of package databases. Cabal manages multiple package databases. There's a system package database, and a user package database. When you compile something with Cabal V1, it uses the union of these package databases. This is a bit of a time bomb, because, as you see, GHC does not like it when you have multiple of the same package. When you issued cabal install network-uri, cabal decided to install one copy of that package into your user database, though you already had one in the system database. When you tried to use ghc, it picked up on the two copies and got confused. Because cabal does not support removing packages, your Haskell installation was pretty much borked, and you reinstalled. I believe you could have done a more conservative rm ~/.ghc, or, had you been really adventurous, used the low-level ghc-pkg command to edit the package database.
Now that you've reinstalled the Platform, I would heavily recommend never using cabal install again. It's old, it's broken, cabal itself tells you not to use it. If you're using the Platform, I think it has stack in it, which is a different build manager, based on Cabal, which is not prone to this kind of breakage. Or, you can just stick to the V2 series of cabal commands, which is what I prefer.
Cabal V2 does not directly support your usecase, where you install a package globally and compile a program against it. This is because doing so is fundamentally broken: global package databases really just don't work for GHC. What Cabal V2 does is install packages into your home directory, ~/.cabal/store. You then have to explicitly tell it which packages you want, and it will construct a package database that contains each required package, without any wonkiness. You can get a REPL with a certain set of packages by issuing (this will take you to a temporary directory; you may need to :cd yourself back.)
cabal v2-repl -b network-uri -b package2 -b etc
If you want to actually compile files with ghc with a set packages, you have to actually define a package with a .cabal file. Here's a stub .cabal file:
name: temporary-pkg
version: 0.0.0.0
build-type: Simple
cabal-version: >=2.0
executable main -- if there is no Main, say "library" instead of "executable <name>"
default-language: Haskell2010
main-is: Main.hs -- only valid in executable stanzas
hs-source-dirs: src -- source files go here
build-depends: base, network-uri, package2, etc -- packages go here
Create and enter a directory, place that in temporary-pkg.cabal, place your sources in src/, and you can issue stuff like cabal v2-build and cabal v2-repl and cabal v2-exec main, etc. cabal will go off and install dependencies from Hackage into ~/.cabal/store as needed. cabal v2-install is therefore not that useful here. In general, v2-installing libraries is unnecessary, but v2-installing packages with executables is useful. Again, for hygiene reasons, you have to list all the packages you are importing from, but you don't need to list their dependencies or anything insane like that.
Cabal V2 still doesn't support uninstalling packages, though the point is that should not be necessary. However, if you find ~/.cabal/store getting too large for your liking, you can just nuke it, and should be built back up as packages are requested.

Craft3e: cabal install not in scope: Applicative

I am attempting to install the code for "Haskell: The Craft of Functional Programming", 3rd edition.
I'm using GHCi, version 7.6.3 on Centos version 7.
Then:
cabal unpack Craft3e
cd Craft3e-0.1.1.0/
cabal install
...
[29 of 67] Compiling CalcParseLib ( Calculator/CalcParseLib.hs, dist/build/CalcParseLib.o )
Calculator/CalcParseLib.hs:132:10:
Not in scope: type constructor or class `Applicative'
Failed to install Craft3e-0.1.1.0
cabal: Error: some packages failed to install:
Craft3e-0.1.1.0 failed during the building phase. The exception was:
ExitFailure 1
I have attempted this installation multiple times, but cannot
overcome this error.
Could I use something other than "cabal install"?
I have plenty to learn about Haskell before I get to this example,
but it would be great to know the installation is fine! :)
You have three options:
Install an older version of the Craft3e package, with e.g. cabal unpack Craft3e-0.1.0.10.
Find Calculator/CalcParseLib.hs in the source files you have downloaded with cabal unpack and add a...
import Control.Applicative
... line next to the other import lines at the beginning. I suspect you will have to do the same with other modules, if the same error shows up elsewhere after you do this change, and there might be other issues of a similar nature.
Install a newer version of GHC (7.6.3 is from 2013). Though the default CentOS repositories won't offer that, there are other options, such as an unofficial Fedora repository and a manual installation. See this page for instructions.
#3 is the definitive solution. If you just want to get started with the book right now, though, you can go for #1 and leave the reinstall for later.
For the sake of reference, here is a brief explanation of the problem (I will use some unfamiliar terms, but you will soon enough learn about them as you study Haskell). There is an important type class called Applicative which, for historical reasons, wasn't as well integrated with the rest of the core libraries as it should be. This situation was corrected in GHC 7.10, which both included Applicative in the Prelude (the module which is imported by default in Haskell programs) and made it necessary to add Applicative instances in a number of places where they were missing. The code in the Craft3e package was updated so that these Applicative instances were in place (cf. this entry in the book's blog), but the import Control.Applicative line, which would be necessary to make the updated code work in older GHCs that do not have Applicative in the Prelude, wasn't added, leading to the error that you are seeing.

attoparsec Illegal equational constraint

as of the time of this writing, I'm running the newest GHC (7.9.20140608) and cabal (1.20.0.0), and it seems that attoparsec is failing.
Data/Attoparsec/ByteString/Internal.hs:519:7:
Illegal equational constraint a_audv ~ (ByteString, t)
(Use GADTs or TypeFamilies to permit this)
In the context: (a_audv ~ (ByteString, t))
While checking the inferred type for ‘succ'’
In the expression:
let
succ' t' pos' more' a
= succ t' pos' more' (substring pos (pos' - pos) t', a)
in runParser p t pos more lose succ'
In the second argument of ‘($)’, namely
‘\ t pos more lose succ
-> let succ' t' pos' more' a = ...
in runParser p t pos more lose succ'’
Am I missing any language extensions? Or would this issue be a little more tricky? Here is my cabal file: http://lpaste.net/105329
Any help with this would be incredible :) Happy Hacking!
For now, the best way to use ghc-7.8 (if your distro package manager doesn't include it) is to go to the ghc download page and follow the directions for the current stable release. There are binary packages, or you can install from source (with a source tarball, this can be as simple as ./configure && make && make install, but you'll need to have a working ghc already).
If you do install from source, you might consider changing the version, e.g. to 7.8.2.1. You can do this by editing the AC_INIT line in configure.ac then executing autoreconf before configure. If you do this, and also install to a version-specific location (e.g. /usr/local/ghc/ghc-7.8.2.1.src, this can be set via ./configure --PREFIX=/path/to/install), you'll be able to have your locally-compiled version installed concurrently with the packaged installation (or platform, or any other versions).
Be advised that ghc-7.8.3 is due out shortly (probably within two weeks at most); it's a bugfix release. Also there is currently no Haskell Platform release that includes ghc-7.8, so that's not an option at this time.

How to check for haskell package versions in ./configure?

how can I tell configure to check for version >= x.y of a given Haskell package?
Thanks,
Use cabalvchk: http://hackage.haskell.org/package/cabalvchk-0.2
For example, to verify that the version of parsec is >= 0.4, you could issue:
$ cabalvchk parsec '>= 0.4'
The return code will be zero if the version constraint is satisfied and non-zero otherwise. The version constraint can be anything cabal understands. An optional third parameter can be non-blank to request verbose output.
I don't know much about configure; can you ask it to run a particular command? If so, then ghc-pkg latest should help you out. For example, here's a run on my machine for the zlib package:
% ghc-pkg latest zlib
zlib-0.5.3.1
% ghc-pkg latest --global zlib
zlib-0.5.3.1
% ghc-pkg latest --user zlib
ghc-pkg: cannot find package zlib
zsh: exit 1 ghc-pkg latest --user zlib
The --global should be used for system-wide installations, and no flag at all for user-specific installations. The --user flag should only be used when you want to check whether a user has a local installation of a package (that may override the global one).
Unless you have a reason not to, I recommend ditching configure in favor of cabal. For cabal, the solution here is to first cabal init in your project's directory, then check that you have a line like this in the .cabal file that's created:
build-depends: zlib >= 0.5
The cabal toolchain is the standard for Haskell projects (because it automates and simplifies many things, including dependency-chasing). You can also ask cabal to invoke configure if there are other dependencies. Open a separate question if you'd like more information about this.
Perhaps the better question is: should you? Checking for a specific version number is one of the great arguments in the autoconf world, and the general winner of the debate is the side which says you should never do it. What specific feature of Haskell do you need? Test for that. As a simple example (unrelated to haskell), suppose your program uses inotify so you want the configury to test if it is available. You could just test if the kernel version is > 2.6.13, but then when Joe tries to build your program on his 2.4.xx version in which he has patched in inotify capability, he's going to be really irritated that your program won't work.
You do not care if Haskell > x.y is available. Instead, there is some specific feature of Haskell that you want that was introduced in x.y; test for that feature.
Using ghc-pkg list, you can get a list of installed versions of a package in ascending order. You should hopefully be able to filter through this list looking for a match. (I don't know how to do this with configure, sorry).
$ ghc-pkg list yesod
/home/ahammar/.haskell/lib/ghc-7.0.2/package.conf.d
/home/ahammar/.ghc/x86_64-linux-7.0.2/package.conf.d
yesod-0.8.2.1
yesod-0.9.1
yesod-0.9.2.2
Try something like this:
# Find ghc-pkg, so we can do version checks
AC_ARG_VAR([GHC_PKG], [Path to ghc-pkg])
AC_PATH_PROG([GHC_PKG], [ghc-pkg])
AS_IF([test -z "$GHC_PKG"], [AC_MSG_ERROR([Cannot find ghc-pkg.])])
# Check that the package actually exists
AC_MSG_CHECKING([for Haskell package foo])
AS_IF([$GHC_PKG latest foo > /dev/null 2>&1],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([Cannot find foo])])
# Check its version
AC_MSG_CHECKING([if foo is new enough])
foo_ver=`$GHC_PKG latest foo | sed 's/^foo-//'`
# At this point you have the version of foo and the minimum version you want.
# The rest of the test is pretty easy to write, use cut and test to compare the
# version numbers. If it's new enough, AC_MSG_RESULT([yes]).
# If not, AC_MSG_RESULT([no]) and AC_MSG_ERROR([foo is not new enough.])

Resources