import qualified as nothing - not an error - haskell

This is as much to add something searchable for the next poor sap, but I'd be interested in knowing why it's not an error.
I needed the FromRow typeclass from postgresql-simple but forgot it was in its own package.
import qualified Database.Postgresql.Simple as P
oops - just want the .FromRow sub-module
import qualified Database.Postgresql.Simple.FromRow
Of course, didn't need it qualified, so stripped the name off the end. However, I forgot to remove the "qualified" keyword.
Generates an error, and much headscratching from me, as I fail to spot the typo:
Not in scope: type constructor or class `FromRow'
Perhaps you meant `Database.PostgreSQL.Simple.FromRow.FromRow' (imported from Database.PostgreSQL.Simple.FromRow)
So - just so this is a question, why is an unnamed qualified import not an error? Is it useful for something, or am I the first person stupid enough to make this mistake?

qualified and as are independent features of imports.
qualified says that the names become available only under qualified names (i.e. names that include the module name).
as simply changes the module name which is used to qualify the names.
So, there are 4 different ways to import a module:
import Database.Postgresql.Simple — both qualified and unqualified names are visible; the qualified ones should be qualified with Database.Postgresql.Simple
import Database.Postgresql.Simple as P — both qualified and unqualified names are visible; the qualified ones should be qualified with P
import qualified Database.Postgresql.Simple — only qualified names are visible and they should be qualified with Database.Postgresql.Simple
import qualified Database.Postgresql.Simple as P — only qualified names are visible and they should be qualified with P

Related

How do I handle Haskell Prelude namespace collisions?

If I want to use readFile from Data.Text.IO, but there's already a readFile in the Prelude, how do I import it, so that it doesn't cause the ambiguity error?
I have a script that just says import Data.Text.IO and then later uses readFile, and I'm testing it in ghci using :load, but it complains about ambiguous function calls.
There are two solutions.
import qualified Data.Text.IO as T
This will give you the Data.Text.IO function as T.readFile. However, if you only plan to use the Data.Text.IO version and never the Prelude version, you can exclude the Prelude version.
import Prelude hiding (readFile)
import Data.Text.IO
An explicit import Prelude will override the default import of Prelude, and you can control which names get imported.
import qualified Data.Text.IO as DTIO, then you can use DTIO.readfile.
see https://wiki.haskell.org/Import for details

GHC import feature or bug

I found that the following code is accepted by GHC:
import Prelude hiding (filter)
import qualified Prelude as P
The idea of these two imports is to make all Prelude functions available as usual, but to require filter to be qualified as P.filter.
I never saw a similar example anywhere, hence my question: is this a feature or a bug in GHC?
Thanks
This is allowed. The import mechanism is very flexible, sometimes surprisingly so.
You can for instance import a module under different names:
import qualified M as A
import qualified M as B
After this, both A.x and B.x will refer to M.x.
Perhaps more surprisingly, you can also import two modules under the same name.
import qualified M as A
import qualified N as A
After this, A.x will refer to either M.x or N.x. If both are defined, an ambiguity error is triggered.
This last feature might seem strange, but after all such ambiguities are already present when importing modules without qualification, so this flexibility does not require any more machinery than the plain import does.
This is a feature and if you search in Github for example you can see this used a lot in the wild.
A widely used idiom is this:
import Data.Text (Text)
import qualified Data.Text as T
This way you don't have to qualify Text in your types and you don't get functions that are conflicting with Prelude functions(like Data.Text.filter, Data.Text.zip etc.).

Haskell *qualified* import of a set of functions

In Haskell, I can import a module qualified by its name or a shortcut name, like so:
import qualified Data.List as List
import qualified Data.Map
I can also import only a select set of functions from a module, or import all functions other than a select set, like so:
import Data.List (sort, intersperse)
import Data.Map hiding (findWithDefault)
Is it possible to import a specific set of functions, like in the import Data.List (sort, intersperse) example above, but to ensure the functions are still identified in a qualified way, such as List.sort and List.intersperse?
Though this does not work, it is the spirit of what I am asking:
import qualified Data.List (sort, intersperse) as List
or perhaps
import qualified Data.List as List (sort, intersperse)
import qualified Data.List as List (sort, intersperse)
This is actually fine and works. The grammar of an import declaration is as follows:
5.3 Import Declarations
impdecl → import [qualified] modid [as modid] [impspec]
qualified and as do not prevent an import specification. This isn't a Haskell2010 addition, as it has been part of the Haskell 98 report.
On the other hand your first example
import qualified Data.List (sort, intersperse) as List
-- qualified impspec! as modid
-- ^ ^
-- +--------------------+
doesn't follow the grammar, as the impspec must be the last element in an import declaration if it's provided.
This is allowed, at least according to the Haskell 2010 Report. First see the examples, which include this one:
import qualified A(x)
Then look up to the actual syntax spec, which indicates that the qualified, as, and "impspec" (the list of imported identifiers or the list of hidden identifiers) are all optional and independent. Thus the syntax genisage describes is actually standard.
Despite the fact that it's not mentioned on https://www.haskell.org/haskellwiki/Import, import qualified Foo as Bar (x, y) seems to work fine for me. I'm running ghc 7.6.3. Maybe that particular wiki page is outdated. If it doesn't work for you, what version of ghc are you using?

Warning: The import of `Module` is redundant except perhaps to import instances from `Module`

I've recently started coding in Sublime Text. This has brought to my attention some warnings I didn't notice when I used Leksah. So I got this one:
import qualified Data.Set as S
Gives:
Warning:
The qualified import of `Data.Set' is redundant
except perhaps to import instances from `Data.Set'
To import instances alone, use: import Data.Set()
On the other hand, either of these two imports from Data.Foldable don't give any warnings:
import Data.Foldable (foldrM, mapM_,foldr,foldl',concat)
-- or
import Data.Foldable
So I'm not really sure what the warning for Data.Set means. I would expect "redundant" means that it's not necessary. If I remove the import it doesn't compile because I'm using a lot of things for Data.Set.
Meanwhile sitting next to it is import qualified Data.Map as M which also gives no warnings.
So I'm completely confused about what that warning is saying.
It generally means either :
you import a module but you don’t use it at all,
you import a module that is already imported by another module you import.
It may be the effect of some refactoring where you don’t use the module anymore. Or maybe you’ve anticipated the future use of this module by importing it.
This message is generated when you compile your project using the -Wall option.
Try to delete the line which shows the error, it often works ;-)

Properly import module with some definitions only visible with qualified names

Suppose I have an module A with names b, c defined.
Now I wish to import A in some way and the following names should be accessible:
A.b
A.c
c
where unqualified name b is hidden.
The method I tried is to import A twice in two ways:
import A hiding (b)
import qualified A (b)
But it doesn't seem to achieve the effect described above. So what is the correct way to do this?
You should be able to do
import A (c)
import qualified A
Or
import A hiding (b)
import qualified A
which should only give you access to c, then everything inside A using the qualified syntax. If you're testing this in GHCi, remember that GHCi has some extra special stuff to allow it more access inside a module that it loaded from source since it's primary use is exploration and debugging.

Resources