[Haskell-cafe] Help understanding type error
Stuart Cook
scook0 at gmail.com
Fri Sep 7 00:20:40 EDT 2007
On 9/7/07, Levi Stephen <levi.stephen at optusnet.com.au> wrote:
> I'm after some help understanding either what I'm doing wrong, or why this error
> occurs.
>
> I have a data type:
>
> > data T a = forall b. (Show b) => T b a
I should first point out that by mentioning b only on the RHS, you've
defined an existential type. If that's what you intended, then fine;
if not, the type you probably wanted was:
data (Show b) => T b a = T b a
which makes most of these problems go away.
> and I want to use/extract 'b' from this.
>
> > extShow (T b _) = b
>
> This gives the following compilation error:
>
> extest.hs:5:0:
> Inferred type is less polymorphic than expected
> Quantified type variable `b' escapes
> When checking an existential match that binds
> $dShow :: {Show b}
> b :: b
> The pattern(s) have type(s): T t
> The body has type: b
> In the definition of `extShow': extShow (T b _) = b
For reasons that I don't claim to completely understand, the compiler
doesn't allow "raw" existential types (such as the type of b) to
escape from their binding scope. See my final comment for a potential
workaround.
> I tried adding a type signature:
>
> > extShow' :: (Show b) => T a -> b
> > extShow' (T b _) = b
The type you've declared is:
extShow' :: forall a b. (Show b) => T a -> b
which carries the implicit claim that for *any* instance of Show the
context desires, we can return a value of that type. This contradicts
the data type, which only contains a value of some *specific* type.
What you really want is something along the lines of:
extShow' :: forall a. exists b. (Show b) => T a -> b -- not valid Haskell!
which unfortunately isn't allowed.
> It seems (to newbie me ;) ) like it should be possible to extract the first part
> of T, and deduce that it is an instance of the class 'Show'.
>
> The following seems ok:
>
> > doShow (T b _) = putStrLn (show b)
You can generalise this to arbitrary functions as follows:
extShowWith :: (forall b. (Show b) => b -> c) -> T a -> c
extShowWith f (T b _) = f b
doShow = extShowWith (putStrLn . show)
This works because f is required to accept *any* Show instance as an
argument type, and so is happy to work for whatever particular type b
happens to inhabit.
Stuart Cook
More information about the Haskell-Cafe
mailing list