Q: Resolving ambiguous type variable

Hal Daume III hdaume@ISI.EDU
Fri, 17 May 2002 10:24:29 -0700 (PDT)


Erm, I think I said something stupid (or at least implied it).

main = getArgs >>= print . first_h

*will* work, because it knows that the result of a getArgs is a list of
Strings.

The problem you originally had was that when you say:

first_h []

The "[]" could refer to a list of any type of element.  Since not every
element type is an instance of Show, it doesn't know that it can apply
show to the list.

By saying, for instance, (first_h ([] :: [Char])) you're saying "okay,
this is an empty list, but it's a list of Characters and you know that a
character can be shown."  If you backtrack what the type checker is doing,
it says:

print (first_h [])

okay, the argument to print must be an instance of Show (print has type
Show a => a -> IO ()).  therefore,

first_h []

must be an instance of Show.  well, what's the type of first_h []?  Well,
the type of first_h is [a] -> Result a.  is "Result a" an instance of
show?  well, let's see...you said data Result a = ... deriving
(Show).  this basically means you get an instance declaration:

instance Show a => Show (Result a) where
  ...some stuf...

so, we want to know if Result a is an instance of show.  Well, it is
whenever a is an instance of show.  so, if the elements of your list are
an instance of show, then (first_h []) is an instance of Show, as we
require.

however, since you just say "[]" it knows this is of type [a], but it
*doesn't* know what a is.  therefore, a could either be or not be an
instance of show.  however, if you explicitly specify what a is and that
explicit type is an instance of show (like Char in my example), then
everything is fine.

--
Hal Daume III

 "Computer science is no more about computers    | hdaume@isi.edu
  than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume

On Fri, 17 May 2002, Hal Daume III wrote:

> In short, you cannot.
> 
> What if your main were:
> 
> main = getArgs >>= print . first_h
> 
> The compiler doesn't know the difference and so it needs a type.
> 
> Simple fix:
> 
> > main = print (first_h ([] :: [Char]))
> 
> 
> --
> Hal Daume III
> 
>  "Computer science is no more about computers    | hdaume@isi.edu
>   than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume
> 
> On Fri, 17 May 2002 tty@SAFe-mail.net wrote:
> 
> > Hello,  
> >    I am writing a function which returns an exception/error string should an unexpected parameter is passed in. Borrowing from the Maybe module I have the following:
> > ------------------------------------------------------------
> > data Result a = Ex String | Value a deriving Show
> > 
> > -- Testing the Result a type
> > first_h :: [a] -> Result a
> > first_h [] = Ex "No list"
> > first_h (x:xs) = Value x
> > 
> > -- Trying out the first_h
> > main :: IO()
> > main = print (first_h [])
> > ------------------------------------------------------------
> > 
> > Which the compiler complains:
> > 
> > Ambiguous type variable(s) `a' in the constraint `Show a'
> >     arising from use of `print' at atype.hs:8
> >     In the definition of `main': print (first_h [])
> > 
> > This is understandable since it is unable to unify the empty list with a concrete list of type 'a' i.e. there are an infinite types which would match. My question is how can I indicate to the compiler that it does not matter which type the empty list is since the return result is of a concreate type.
> > 
> > Thanks
> > 
> > Tee
> > _______________________________________________
> > Haskell-Cafe mailing list
> > Haskell-Cafe@haskell.org
> > http://www.haskell.org/mailman/listinfo/haskell-cafe
> > 
> 
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>