error-messages icon indicating copy to clipboard operation
error-messages copied to clipboard

Ambiguous occurrence ‘map’

Open tomjaguarpaw opened this issue 3 years ago • 14 comments

A new user reports confusion about the error message below. I can understand the confusion. The error message is technically correct, of course, but wouldn't it be more helpful to say "To resolve the error change map to Prelude.map or Data.Map.map (if either of those is what you meant) or something else (if you meant something else.".

(Implicit import of Prelude is a confounding factor here.)

<interactive>:12:2: error:
    Ambiguous occurrence ‘map’
    It could refer to
       either ‘Prelude.map’,
              imported from ‘Prelude’ at modules.hs:1:1
              (and originally defined in ‘GHC.Base’)
           or ‘Data.Map.map’,
              imported from ‘Data.Map’ at modules.hs:5:1-15
              (and originally defined in ‘Data.Map.Internal’)

EDIT, the op's code which produced the error:

import Data.List (nub, sort)  --you can selectively import functions
{-import Data.List hiding (nub)  you're importing all functions accept the nub-}
-- import qualified Data.Map as M  
-- Now, to reference Data.Map's filter function, we just use M.filter
import Data.Map
import qualified Data.Set
  
numUniques :: (Eq a) => [a] -> Int  
numUniques = length . nub

tomjaguarpaw avatar Aug 01 '21 08:08 tomjaguarpaw

I'm unsure about this one. I definitely think that the Prelude import should be noted as implicit ("part of the implicit import of Prelude" instead of the first line under "Prelude.map"). But I'm unsure how to improve the rest of the message without making the new message worse for more knowledgeable users. Maybe change "It could refer to" to "To disambiguate, use either"?

Really, I think what would be best for the particular complaint you linked to is to have a web page for every error, explaining it in more detail and linking to resources about e.g. module imports.

goldfirere avatar Aug 02 '21 16:08 goldfirere

@goldfirere I think something as simple as the current purescript error messages, that have a link to a page with (hopefully) more information about the error, what causes it, how to solve it, etc would be a great step forward, with (I assume) a much lower barrier to develop than revamping GHC error message handling to display richer output.

As an example, when failing to unify types, the user gets a link to this page. https://github.com/purescript/documentation/blob/master/errors/TypesDoNotUnify.md

elland avatar Aug 03 '21 08:08 elland

Really, I think what would be best for the particular complaint you linked to is to have a web page for every error, explaining it in more detail and linking to resources about e.g. module imports.

I believe that is suggested in #10

noughtmare avatar Aug 03 '21 15:08 noughtmare

As part of reviewing this, I do my best to emulate what the original op experienced. In essence, I want to understand "what was confusing about the error message". To do so, we often need to take into account the reader's level of familiarity and understanding of the various topics that are relevant in the situation.

In this case, the intention appears to be:

"import and use the map function from Data.Map".

In doing so, and in the most straightforward way (eg without a qualified import), GHC was then confused:

did the user mean map from Data.Map or Prelude? I need to know which specifically.

The fix is any of a few ways to make more clear and explicit to GHC, the reference to "which" map we intend to be used (we could disable the implicit prelude, use a qualified import, reference Data.Map.map more explicitly, etc).

The problem I see here is:

  • The current error message is rather correct and concise and on point with the issue on the surface "There are several Foos and I don't know which Foo you refer to".
  • Often, the user will have made multiple imports which leads to GHC's confusion, and the solution is easier to realize (GHC is telling me something about X and Y, and those are things I imported, let me look at them, oh, I see a conflict there.. versus: what is this prelude thing?).
  • In this particular case, the conflicting map is in Prelude, which the user did not import. Thus, the user needs to know/understand what the prelude is, and the fact that there is a map function in there. They are asking "what's the conflict, I want to use map from Data.Map". If we don't know about Prelude, or why/what qualified imports are useful, the error message is speaking to us in a different context than we are thinking.

At times, this error message is out of context WRT the user's frame of reference, and at other times will come up under the correct context.

Updates to the error message would need to be very careful, as we could easily increase confusion in the other contexts where this message comes up.

I don't see an obvious change to the error message here, but this is perhaps better resolved with clear documentation about the error message and different contexts it may come up, what the solutions are for those different contexts, etc.

ketzacoatl avatar Aug 07 '21 16:08 ketzacoatl

On the topic of links/urls in error messages:

At least with this situation, to be helpful GHC's references would need to include the Prelude topic as well as qualified imports. It'd be a little more challenging for GHC to figure out ("introspect into") the confusing references enough to conclude that the Prelude was involved, as not all instances where this message is relevant would include the Prelude.

ketzacoatl avatar Aug 07 '21 16:08 ketzacoatl

@tomjaguarpaw Thank you for bringing the user's experience across from discourse to this project for tracking and discussion, and hopefully some improvements.

I hope you don't mind, but I'd like to edit your original description to include the Op's source code from discourse, as I believe that is necessary for evaluating the message in their context.

ketzacoatl avatar Aug 07 '21 16:08 ketzacoatl

On the topic of links/urls in error messages:

I think that there should be one page for the general error message and then on that page there might be a list of possibilities that, for example, could link through to information about the Prelude, so then GHC wouldn't have to do any extra work.

noughtmare avatar Aug 07 '21 17:08 noughtmare

There is now also another error reported on discourse that has another extra angle, namely that the Main module is mentioned while it is never explicitly declared by the user because there is no module Main header. That would also be something that could be listed on such an error message information page.

For completeness here's the code:

(!!) :: [a] -> Int -> a 
(x:_) !! 0 = x
(_:xs) !! n = xs !! (n-1)

With this error message:

Index.hs:3:18: error:
    Ambiguous occurrence ‘!!’
    It could refer to
       either ‘Prelude.!!’,
              imported from ‘Prelude’ at Index.hs:1:1
              (and originally defined in ‘GHC.List’)
           or ‘Main.!!’, defined at Index.hs:2:7
  |
3 | (_:xs) !! n = xs !! (n-1)
  |                  ^^

noughtmare avatar Aug 07 '21 17:08 noughtmare

I hope you don't mind, but I'd like to edit your original description to include the Op's source code from discourse

That's fine. I'm happy to hand the issue over to you.

tomjaguarpaw avatar Aug 07 '21 18:08 tomjaguarpaw

Trying to bring this to something actionable:

I can extract the following suggestions:

  • Mark implicit imports of Prelude as such
  • Change "It could refer to" to "To disambiguate, use either"
  • In any message mentioning Main. but the Main was implicit, have a NB: Modules without a module header define a module named 'Main'.

Does that sound about right? I'm not convinced this actually solves the original problem, but it would be an improvement over the status quo, waiting for a more general approach to have error messages link to information pages.

goldfirere avatar Aug 31 '21 14:08 goldfirere

Here is another beginner on Reddit having problems interpreting a similar error message: https://reddit.com/r/haskell/comments/pmsl45/how_to_fix_ambiguous_occurrence_error_haskell/

Code:

product :: [int] -> int
product [] = 1
product (n:ns) = n * product ns

Error:

producter.hs:3:22: error:
    Ambiguous occurrence ‘product’
    It could refer to
       either ‘Prelude.product’,
              imported from ‘Prelude’ at producter.hs:1:1
              (and originally defined in ‘Data.Foldable’)
           or ‘Main.product’, defined at producter.hs:2:1
  |
3 | product (n:ns) = n * product ns
  |                      ^^^^^^^
Failed, no modules loaded.

noughtmare avatar Sep 12 '21 13:09 noughtmare

Perhaps we could add a more detailed message for recursive functions that are ambiguously used inside their own definition. Something like:

You are defining a function 'product', but that is already defined in the module 'Prelude'.
To fix this you can do one of the following things:
  * Hide the existing function by writing `import Prelude hiding (product)`. 
  * Import the Prelude module qualified with `import qualified Prelude`.
  * Give your function a different name.

This is just a rough sketch of what an error message might look like, I'm still very much open for suggestions.

noughtmare avatar Sep 12 '21 13:09 noughtmare

I think phrasing it with more familiar jargon might be helpful, like "this function is defined in the automatically imported standard library (the module Prelude)"

tek avatar Sep 12 '21 17:09 tek

There's another way to fix, too: the recursive occurrences can be written qualified. Example:

module M where

product = ... M.product ...

So I think the more general message works in the recursive case, too. Of course, those other suggestions (e.g. hiding) may also be helpful. But I'm leery of cluttering up our messages with lists of all possible ways to fix, especially if there are more than two. Instead, I'd rather have all these fixes on a web page that describes the error and can provide fixes with examples.

With IDE integration and code actions, we absolutely should forward all the fixes to the IDE. We can also imagine the command-line interface having a -fshow-fixes flag that has GHC print representations of all of its suggestions.

Happy for pushback here!

goldfirere avatar Sep 13 '21 15:09 goldfirere