Haskell: dealing with ambiguous imports - haskell

I'm getting ambiguity warnings, sometimes errors, all the time. This is just a clear cut example. I'm using doctest:
$ stack exec doctest -- src/Main.hs
<interactive>:6:14:
Ambiguous occurrence ‘stdout’
It could refer to either ‘Turtle.stdout’,
imported from ‘Turtle’ at src/Main.hs:6:1-13
(and originally defined in ‘Turtle.Prelude’)
or ‘System.IO.stdout’,
imported from ‘System.IO’
(and originally defined in ‘GHC.IO.Handle.FD’)
...
Examples: 2 Tried: 2 Errors: 0 Failures: 0
It obviously works, at least for the time being, but these warnings are voluminous, annoying, and probably dangerous.
I tried to cope with hiding, like this (Main.hs, all the imports):
import Turtle
import Prelude hiding (FilePath)
import System.IO hiding (FilePath, stdout, stderr) -- trying to hide std...
import Text.Regex.TDFA
but it makes no difference.
Is there a correct general approach?

Well you could edit your .ghci file and include
:m - Prelude
this way GHCi should not preload the Prelude but like Jubobs I would suggest that you don't reuse those names in the first place or that you import (qualified) with some combination of
import Turtle hiding (stdout)
import qualified Turtle as T
import Turtle ( noOverlappingFunc, NonOverlappingType )
it's just the minor inconvenience of writing
T.stdout
instead.
IMHO it's not a good idea to hide stuff from the Prelude to much - aside from the problems you saw there is always the problem of peaple reading your code and their expectations

Related

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.).

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 ;-)

Unable to import modules in haskell

I'm really new to haskell, and I'm having a problem importing any modules whatsoever.
When I load an .hs file that contains nothing but
import Data.list
it gives me an error of
file.hs:1:8: parse error on input Data.list
I know I must be making a really basic error somewhere, because imports seem to be working for everyone else, even in all the tutorials. Is it because I've changed my directory with :cd? Or is it how my GHCi was downloaded?
Modules start with capital letters
import Data.List
Module names are capitalized.
Capitalize the word "List".
import Data.List

Explain Haskell empty import list ()

I saw much lines like import HSP.ServerPartT() - list of imports is empty. Why is this done? What difference with just not importing this module?
It imports only typeclass instances from the module. With -Wall, GHC issues a warning for modules that are imported but from which no definitions are used:
foo.hs:1:1:
Warning: The import of `M' is redundant
except perhaps to import instances from `M'
To import instances alone, use: import M()
The empty import list silences this warning and serves as documentation of the purpose of the import.
That form imports nothing but the instances from that module. And that's the reason of that form, you want to have the instances in scope, but nothing else.

Why is import of an abstract type not necessary, when using functions which work with values of that type

Following the excercises in chapter 5 of Real World Haskell, I end up with Prettify.hs, which exports among other things an abstract type Doc and a rendering function compact, which is a function from Doc to String. Another file, PrettyJSON.hs exports renderJValue, which ends up giving me a Doc value. In my main, I import just renderJValue and compact, and use the output of the one as input to the other. I am confused why this works. I would think that it would also have been necessary to import the abstract Doc type. Can Haskell see that the two functions fit together without the Doc imported?
For illustration, this is my Main.hs:
module Main where
import System.IO
import SimpleJSON (JValue(..))
import PrettyJSON (renderJValue)
import Prettify (compact)
main = do
let val = renderJValue $ JString "foo"
putStrLn $ compact val
getLine
which outputs
"foo"
Can Haskell see that the two functions fit together without the Doc imported?
Yes.
To elaborate a bit, what you import is only saying what's in your local namespace, so to mention the Doc type in a type signature, you'd have to import it. ghc is doing a lot of matching up types (and hunting down modules) in the background when loading the dependencies of your code, too, but such matters are implementation detail.

Resources