There is no instance for (Show a0) resulting from the use of `print 'The type of the variable` a0' is ambiguous

data NestedList a = Elem a | List [NestedList a] flatten :: NestedList a -> [a] flatten (Elem element) = [element] flatten (List []) = [] flatten (List (first:rest)) = flatten first ++ flatten (List (rest)) main = print $ flatten $ List [] 

I wrote the above code in haskell. When I execute this with any other parameter like

 main = print $ flatten $ List [Elem 1, Elem 2] main = print $ flatten $ Elem 1 

He gives

 [1, 2] [1] 

respectively.

Cannot execute it with an empty list.

 main = print $ flatten $ List [] 

Error message

 No instance for (Show a0) arising from a use of `print' The type variable `a0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance Show Double -- Defined in `GHC.Float' instance Show Float -- Defined in `GHC.Float' instance (Integral a, Show a) => Show (GHC.Real.Ratio a) -- Defined in `GHC.Real' ...plus 23 others In the expression: print In the expression: print $ flatten $ List [] In an equation for `main': main = print $ flatten $ List [] 

Questions

  • Why is this failing and how can I fix it?
  • Should I change the definition of NestedList to accept an empty List ? If so, how to do it. This is pretty confusing.
+7
haskell
source share
4 answers

The problem is that the compiler cannot know the type flatten $ List [] . Try to figure out the type yourself, you will see it [a] for some a , and print requires that its argument be an instance of Show , and [a] is an instance of Show if a is an instance of Show . Even though your list is empty, so there is no need for any restrictions on a to represent [] , so the compiler does not know.

Thus, you need to create an explicit type annotation (for any type for which a Show instance exists):

 main = print $ flatten $ List ([] :: [NestedList Int]) 

or

 main = print $ flatten $ List ([] :: [NestedList ()]) 

or

 main = print fl where fl :: [()] fl = flatten $ List [] 
+7
source share

The list type is polymorphic. Since you are not providing an element, just an empty list constructor [] , there is no way to infer what type of list it is.

This is: [] :: [Int]

or [] :: [Maybe (Either String Double)] . Who said?

You. Provide a type annotation to resolve polymorphism, then the GHC can send to the corresponding show instance.

eg.

 main = print $ flatten $ List ([] :: [Int]) 
+15
source share

To add to the answers here already, you can object "but what does it matter, what things are on my list, it does not have any of them!"

Well, firstly, it is easy to construct situations in which it is not clear whether it is empty or not, and, in any case, type checking does not like to look at values, it just wants to look at types. This simplifies the job because it means that when it comes to values, you can be sure that you already know all the types.

Secondly, it really matters what it is, even if it is empty:

 ghci> print ([] :: [Int]) [] ghci> print ([] :: [Char]) "" 
+8
source share

[] can be a list of float, string, booleans, or any type in general. Thus, print does not know which instance of show use.

Do as the error message says, and enter an explicit type, as in ([] :: [Int]) .

+2
source share

All Articles