Strange error in show for datatype
Simon Peyton-Jones
simonpj@microsoft.com
Wed, 3 Oct 2001 08:25:58 -0700
Interesting. The difficulty (which GHCi has too) is this. Consider
expr =3D Str "foo"
msg =3D show expr
Hugs wants to print msg. What are the types?
expr :: forall a. LispList a
msg :: forall a. Show a =3D> String
Urk! What "Show" dictionary should Hugs use when evaluating "msg"?
You may say "it doesn't matter", but in general that's not the case. =20
In the case of class Num, for example, we might have
expr =3D 3+4
msg =3D show expr
and then the type involved really does matter. In the case of Num
there are defaulting rules, but not for arbitrary user types.
What is particularly annoying here is that it's intuitively obvious that
if we have an expression of type (forall a. LispList a) then it can't
have any useful values of type 'a' in it. So we can't need to show any
of them. Hmm.
I wonder if the following is true. Given the ambiguous type
forall a. Show a =3D> T (where a does not appear in T)
it's OK to pass the bottom dictionary. Furthermore, I claim that=20
what makes it OK is that Show has no methods that have 'a'=20
in the result that do not also have 'a' in an argument. The Bad Methods
are like those in Num and Read:
class Num a where
fromInteger :: Integer -> a -- Bad guy
...
class Read a where
read :: String -> a -- Bad guy
...
So (my claim) if none of the classes of the ambiguous type
have a method that returns an a-value, we can definitely=20
replace the dictionary with bottom.
Indeed, if none of the classes have a method that returns
an a-value without also consuming one (urk-- strictly, I think, sigh)
then the same holds.
In which case we could report ambiguity a bit less often. How
useful this would be I don't know.
Simon
| For a change, a teacher asking for help on behalf of a student....
|=20
| I have a student who wants to emulate S-expressions of Lisp=20
| in Haskell. He came up with the following data type:
|=20
| data LispList t =3D Atom t | LispList [LispList t] | Str [Char]
|=20
| This works just fine. He then wanted to make it an instance=20
| of Show, in order to print values of this type:
|=20
| instance Show t =3D> Show (LispList t) where
| show (Atom t) =3D show t
| show (LispList t) =3D show t
| show (Str t) =3D show t
|=20
| Now, this compiles and works for some values of the type, but=20
| not for all! Here is what happens in hugs:
|=20
| hugsprompt> (Atom 1) =3D=3D> 1
| hugsprompt> (LispList [Atom 1, Str "HEJ"]) =3D=3D> [1,"HEJ"] =
(LispList=20
| hugsprompt> [Atom 1, LispList [Str "HEJ"]]) =3D=3D> [1, ["HEJ"]] (Str =
| hugsprompt> "HEJ") =3D=3D> "Cannot find show function...." =20
| (LispList [Str=20
| hugsprompt> "HEJ"]) =3D=3D> "Cannot find show function...." =20
| (LispList [Str=20
| hugsprompt> "HEJ",Atom 1]) =3D=3D> "Cannot find show function...."
|=20
| So there is a problem when the value is of form Str string or=20
| where such a value is first in the list l in a value of the=20
| form LispList l. Oddly enough, such values may appear at=20
| other positions without causing any problems.
|=20
| I don't think there is a bug in hugs. Similar problems appear=20
| if the Show instance is derived, and ghc will also complain -=20
| if the definition f =3D show (LispList [Str "HEJ"]) is=20
| compiled, for instance, the compiler will complain about=20
| ambiguous contexts. Ghc will say
|=20
| Enrico.hs:1: Ambiguous context `{Show taKi}'
| `Show taKi' arising from use of `show' at=20
| Enrico.hs:17
|=20
| and hugs
|=20
| Reading file "Enrico.hs":
| Type checking =20
| ERROR "Enrico.hs" (line 17): Unresolved top-level overloading
| *** Binding : f
| *** Outstanding context : Show b
|=20
| So I wonder whether the infamous Monomorphism Restriction is=20
| lurking somewhere here? But I cannot see exactly how right=20
| now. Does anyone else have a clue?
|=20
| Bj=F6rn
|=20
| _______________________________________________
| Haskell mailing list
| Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
|=20