"too polymorphic" type error

Fergus Henderson fjh@cs.mu.oz.au
Tue, 1 Aug 2000 15:58:19 +1000


On 31-Jul-2000, Shiv <shiv@balrog.ece.ucsb.edu> wrote:
> 
> I am getting an unfamiliar type error and wondered if somebody could
> tell me what I am doing wrong.

I'm not an expert in Clean, and I don't have the Clean language
reference manual at hand, so I could be wrong about this...
but I do have a bit of experience in Haskell, and my guess is
that problem here is probably the same as one that comes up
in Haskell every now and then.

...
> binSort :: (b a -> Bool) [b] [a] -> [[a]]
> binSort isInBin bins elems
>     = last (scan (insertInBin bins) ([[] \\ b <- bins]++[[]]) elems)
> where
>     insertInBin :: [b] [[a]] a -> [[a]] // Type Error here ************
>     insertInBin [] [as:ass] e = [[e:as]:ass]
>     insertInBin [bin:bins] [as:ass] e
>     | isInBin bin e = [[e:as]:ass]
>                     = [as:insertInBin bins ass e]
...
> Type error [test3.icl,11,insertInBin]: specified type is too
> polymorphic (contains monomorphic type variables)

I think the problem here is with the scope of the `b' in the type
declaration for `insertInBin'.  If you write a type declaration
for `insertInBin', then I think the scope of the type variables
in that declaration will be local to that declaration.  That is,
the `b' in the declaration of `insertInBin' is a different type
variable from the `b' in the declaration of `binSort'.  Your
declaration implicitly means

	insertInBin :: forall a b . [b] [[a]] a -> [[a]]

However, `insertInBin' is not fully polymorphic in this way,
since it uses the `isInBin' parameter from its environment.
The actual type inferred from `insertInBin' will be

	insertInBin :: forall a . [b] [[a]] a -> [[a]]

where the `b' here is the same type variable as the `b'
in the type declaration for the outer function `binSort'.
Unfortunately, there is probably no way to write such a type!
At least in Haskell 98 there isn't.  I don't know if Clean
provides any syntax for it, but I suspect not.

So, you can leave that type declaration out; or you can pass
`isInBin' as an explicit parameter to `insertInBin', thus ensuring
that the type of `insertInBin' does not depend on any of the type
variables in its containing function's type declaration, so that
you can write a type declaration for it.

-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3        |     -- the last words of T. S. Garp.