Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No instance for (Show a0) arising from a use of `print' The type variable `a0' is ambiguous

Tags:

haskell

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 seen code in haskell. When I execute this with any other parameter, for example

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

It gives

[1, 2]
[1]

respectively.

It fails when I 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

  1. Why does it fail and how can I fix this?
  2. Should I change my NestedList definition to accept an empty List? If so, how do I do that. Its quite confusing.
like image 288
thefourtheye Avatar asked Sep 04 '13 13:09

thefourtheye


2 Answers

The list type is polymorphic. Since you don't supply an element, just the empty list constructor [], there's no way to infer what list type this is.

Is it: [] :: [Int]

or [] :: [Maybe (Either String Double)]. Who's to say?

You are. Supply a type annotation to resolve the polymorphism, then GHC can dispatch to the correct show instance.

E.g.

main = print $ flatten $ List ([] :: [Int])
like image 145
Don Stewart Avatar answered Sep 21 '22 06:09

Don Stewart


To add to the answers here already, you may object "but what does it matter what type of things my list contains? it doesn't have any of them in it!"

Well, first of all, it is easy to construct situations in which it's unclear whether or not the list is empty, and anyway type checking hates to look at values, it only wants to look at types. This keeps things simpler, because it means that when it comes to deal with values, you can be sure you already know all the types.

Second of all, it actually does matter what kind of list it is, even if it's empty:

ghci> print ([] :: [Int])
[]
ghci> print ([] :: [Char])
""
like image 42
Ben Millwood Avatar answered Sep 19 '22 06:09

Ben Millwood