Haskell Hidden Packages: Data.HashSet - haskell

I'd like to use Data.HashSet in Haskell. So I put import Data.HashSet at the beginning of my program. GHCi complains: Could not find module Data.HashSet.
My questions are:
How can I get Data.HashSet to work?
I've read somewhere that this is part of a hidden module or package. Why is the module hidden? Does "hidden" mean that I should not use it?
If I should not use it, is there a better alternative for a haskell data structure with a near-constant lookup time?

Data.HashSet is a module in the unordered-containers package, and also in the hashmap package. If you have either package installed,
import Data.HashSet
should work out of the box, since it is an exposed module of both packages. To install it (using unordered-containers, since that is the commonly used one),
cabal update
cabal install unordered-containers --dry-run
-- check that it wouldn't reinstall anything, if all's fine
cabal install unordered-containers

Related

How do you import a Haskell module that was installed using Cabal?

I installed the timezone-series Haskell module using cabal install timezone-series-0.1.5.1.
I then defined a module named Main.hs that starts with:
import Data.Time.LocalTime.TimeZone.Series -- from timezone-series-0.1.5.1
when I run ghc Main.hs, GHC throws the following error:
/home/ubuntu/Main.hs:2:1: error:
Failed to load interface for ‘Data.Time.LocalTime.TimeZone.Olson’
I tried explicitly including the cabal directory in GHC's search path using:
ghc -i/home/ubuntu/.cabal/lib/x86_64-linux-ghc-8.0.2/timezone-olson-0.2.0-KqRNJj3zomR7zz2Yx6P5Oq/ Main.hs
This resulted in the correct path being searched, but GHC is only looking for files ending in the suffix ".hs":
Locations searched:
...
/home/ubuntu/.cabal/lib/x86_64-linux-ghc-8.0.2/timezone-olson-0.2.0-KqRNJj3zomR7zz2Yx6P5Oq/Data/Time/LocalTime/TimeZone/Series.hs
/home/ubuntu/.cabal/lib/x86_64-linux-ghc-8.0.2/timezone-olson-0.2.0-KqRNJj3zomR7zz2Yx6P5Oq/Data/Time/LocalTime/TimeZone/Series.lhs
/home/ubuntu/.cabal/lib/x86_64-linux-ghc-8.0.2/timezone-olson-0.2.0-KqRNJj3zomR7zz2Yx6P5Oq/Data/Time/LocalTime/TimeZone/Series.hsig
/home/ubuntu/.cabal/lib/x86_64-linux-ghc-8.0.2/timezone-olson-0.2.0-KqRNJj3zomR7zz2Yx6P5Oq/Data/Time/LocalTime/TimeZone/Series.lhsig
Cabal installed interface files instead however:
/home/ubuntu/.cabal/lib/x86_64-linux-ghc-8.0.2/timezone-olson-0.2.0-KqRNJj3zomR7zz2Yx6P5Oq/Data/Time/LocalTime/TimeZone/Olson.hi
From line 318 of GHC's source code it looks like GHC ignores "*.hi" files unless it is called in single-shot mode (with the -c flag). Is this correct? (See: https://github.com/ghc/ghc/blob/67a5a91ef5e61f3b3c84481d8a396ed48cd5d96e/compiler/GHC/Unit/Finder.hs)
How can I get GHC to import this module?
An help will be greatly appreciated!
My suggested ways of installing packages in order of my preference:
Make a cabal package and add timezone-series you want to install to the build-depends field as described in the cabal manual.
Use the experimental cabal-env tool to basically automate the process of point 3 below, but then with the global environment. This makes a new build-plan every time you install a new package, so it is like removing the package environment and building it again with all the old packages and the new package added to it. You can add specific constraints like this: cabal-env "timezone-series == 0.1.5.1".
Install a package into local package environment with cabal --package-env . --lib timezone-series. You can add as many packages as you want after the --lib option to install more than one package. If you later want to use a different set of packages simply remove the .ghc.environment.* file that is generated and rerun the installation with a new set of packages. GHC will automatically use these package environment files that are in the current or parent directories. You can specify specific constraints with the --constraint option like this: --constraint "timezone-series == 0.1.5.1".
Use cabal install --lib timezone-series to install it directly into the global environment (~/.ghc/x86_64-linux-8.0.2/environments/default), this will fail if a conflicting package was installed earlier. When you run into errors you can remove that package environment and try again.
Finally, I want to note that GHC 8.0.2 is quite old, so I would advise you to upgrade if you don't have a specific reason for using that version.

What should I do if two modules share the same name?

I have two packages that provide modules with the same name. When I try to load the module I get an error
Ambiguous interface for ....: It was found in multiple packages.
What should I do to resolve this?
To be specific, both the cryptonite package and crypto-api package provide modules with the name Crypto.Random. How can I specify which package I want to load the module from?
If you happen to be using ghc >= 8.2 and cabal-install >= 2.0, another option is renaming the conflicting modules in the mixins section of the cabal file:
build-depends: base >=4.10 && <4.11,
cryptonite >= 0.24,
crypto-api >= 0.13.2
mixins:
cryptonite (Crypto.Random as CryptoniteCrypto.Random),
crypto-api (Crypto.Random as CryptoAPICrypto.Random)
You can then import the renamed modules:
module Main where
import CryptoniteCrypto.Random
import CryptoAPICrypto.Random
One thing to take into account when renaming this way is that modules that haven't been explicitly renamed become inaccessible.
In fact, ability to rename modules seems to exist since GHC 7.10, through the -package flag and the reexported-modules cabal section. reexported-modules works at declaration-time (when publishing a package) while mixins works at use-time (when depending on a package).
You can use the PackageImports language pragma and explicitly pick the package you mean in your import statement like so:
import "cryptonite" Crypto.Random
Alternatively if you have both installed but are only using one of them, you could explicitly list the dependencies you use in a cabal file and build via cabal.

Haskell: where is Data.Numbers.Primes library?

I tried importing Data.Numbers.Primes
import Data.Numbers.Primes
runhaskell gave me:
5.hs:1:8:
Could not find module `Data.Numbers.Primes'
Use -v to see a list of the files searched for.
ghci gave me:
<no location info>:
Could not find module `Data.Numbers.Primes'
It is not a module in the current program, or in any known package.
I tried to install Data.Numbers.Primes through cabal, but I got:
cabal update
...
cabal install Data
cabal: There is no package named 'Data'.
You may need to run 'cabal update' to get the latest list of available
packages.
cabal install Data.Numbers.Primes
cabal: The file does not exist 'Data.Numbers.Primes'.
help?
The package you're looking for is called primes.
There's no rule that the package will be called the same as its top-level module name. Typically, packages put themselves under whatever makes sense, but that's pretty much arbitrary. When in doubt, Hackage search helps.

Cabal failing to install vector-space package

When I try to install the spacepart package using cabal install it tries to compile a dependency vector-space but when vector-space tries to compile a module it exports "Data.LinearMap" I get the error "Not in scope type constructor or class "HasTrie". After I did some digging HasTrie is a class exported by the MemoTrie package. Thing is I have MemoTrie installed and MemoTrie exports "HasTrie". What is wrong here?
Also this stack overflow post doesnt help so this isnt a duplicate question: Haskell package vector-space fails at compile time
-Thank you for your time
As far as I can see from browsing on Hackage, spacepart is fixed to use a very old version of vector-space (0.5.*), and that version's Data.LinearMap contains the suspicious import line
import Data.MemoTrie ((:->:)(..))
which simply doesn't import HasTrie. My guess is that at some time in the past, this actually worked, because (:->:) is a data family defined inside HasTrie, but that GHC has since been changed so it doesn't.
Possible dirty fix: I note that until 0.5.2, it simply says
import Data.MemoTrie
I just tried installing with
cabal install spacepart vector-space-0.5.2
and it seemed to work.

Control.Monad.State found in multiple packages haskell

While evaluating the line "import Control.Monad.State" in a Haskell module, GHC gives me the following error:
Could not find module `Control.Monad.State':
it was found in multiple packages: monads-fd-0.0.0.1 mtl-1.1.0.2
Failed, modules loaded: none.
How do I resolve this conflict?
You have several options. Either:
ghc-pkg hide monads-fd. This will cause GHC and GHCi to ignore the presence of the monads-fd by default until you later ghc-pkg expose monads-fd, but software installed by Cabal will still be able to build against it.
Use the {-# LANGUAGE PackageImports #-} pragma, and change your import statement to import "mtl" Control.Monad.State.
Use Cabal to build your project, and specify mtl in the Build-depends line.
The first is best for casual hacking, and the last is best for production builds.
These all assume you want the mtl module and not the monads-fd module; otherwise swap them.
Both packages implement Control.Monad.State and GHC does not know which implementation it should prefer, so you need to hide one of the packages from GHC. Seems like the -ignore-package <name> GHC flag might help you here.

Resources