[clean-list] a local function typing question in function composition

Edsko de Vries devriese at cs.tcd.ie
Thu Apr 12 17:46:49 MEST 2007


Hi,

> >Then when it checks the body of f ("y"), it must check that y has
> >type "a", where "a" is the type of the argument passed in (x). This
> >is indeed  a different a, BUT "y" has type "a" *for every a*, so that
> >doesn't matter!
> 
> This is the part that I do not understand. "y" has type "a, for every
> a" but it seems to me that this type is too general. I would have
> thought that "y" needs to have the exact same type as "x".

But it does! In this example, y has every type, and therefore it also
has the same type as x :) See example below.

> Indeed, if you look at the program as a whole, it doesn't make sense,
> because "undefined" could return anything, and thus the actual value
> that "y" gets could  be anything.  I would argue that this example
> actually shows up a problem in the  Clean type system, because the
> caller of "f" wants a value back which is of the same  type as the
> value passed in.

Actually, the point is that undefined won't return anything at all, and
therefore it is safe to assume it has every type. 

> The only reason this "works" (and here I am  using "works" very very
> loosely) is that the function "f" never terminates when called, so it
> is impossible to  actually inspect the returned value. If "f" actually
> returned a value, then this would  clearly be a bug.

No, not really. I am sorry that my use of "undefined" muddled the
waters. Here is a similar example that doesn't use undefined, and does
in fact return a value:

module t

f :: [a] -> [a]
f x = y
    where
        y :: [a]
        y = []

Start = f [1,2,3]

The empty list [] has type "[a]" (list of a) for every a (the empty list is a
list of integers, a list of bools, etc.). Now exactly the same argument holds:
y has type [a] for every a. The signature of f says that the result must have
the type type as the input, but since y has type [a] for every a, that's not a
problem. This program is type-correct and runs (and returns []).

> Never-the-less, from a practical prospective, I have learned the
> following:
> 
>     The type variables used in inner type declarations are ALWAYS
>     different from the type variables in outer type declarations.
> 
> If I remember this rule, I think I can understand and avoid typing
> errors.

Yes, if you find yourself using a type variable in an inner function which you
have also used in an outer function, chances are you are trying to do something
that won't work.

> It would be helpful if the error message
> 
>     Type error [t.icl,6,y]:type variable of type of lifted argument a
>     appears in the specified type
> 
> could be changed to be a little bit more comprehensible. 

I agree, but that's not up to me I'm afraid :)

Edsko


More information about the clean-list mailing list