[isabelle-dev] Additional type variable(s) in specification

Brian Huffman brianh at cs.pdx.edu
Thu Dec 2 15:44:19 CET 2010


On Wed, Dec 1, 2010 at 11:50 PM, Tobias Nipkow <nipkow at in.tum.de> wrote:
> Is the following behaviour really a good idea and useful?
>
> inductive P :: "nat => bool" where
> "P(suc n)"
>
> is accepted but defines
>
> P :: "'a itself => nat => bool"
>
> It does kind of warn me by saying
>
> ### Additional type variable(s) in specification of P: 'a
>
> but if you miss that warning, you will be very surprised about the kind
> of errors you get later on when using P.
>
> If I give a constant an explicit type, I would prefer Isabelle to
> respect that.
>
> Tobias

This "feature" seems to originate here:
http://isabelle.in.tum.de/repos/isabelle/rev/09e238561460

Another complaint about this behavior appeared recently on the users
mailing list:
https://lists.cam.ac.uk/pipermail/cl-isabelle-users/2010-November/msg00065.html

I agree that the least confusing/surprising behavior would be to have
definitions like this (taken from the NEWS file) produce an error
message:

definition unitary :: bool where "unitary = (ALL (x::'a) y. x = y)"

In the rare case where someone actually wants to have the definition
depend on a type variable, it is not a burden to write it explicitly:

definition unitary :: "'a itself => bool" where "unitary (t::'a
itself) = (ALL (x::'a) y. x = y)"

(It used to be possible to write TYPE('a) as a lhs pattern in
definitions, like "unitary TYPE('a) = (ALL (x::'a) y. x = y)". Why
doesn't this work any more?)

This also has the benefit of more clearly indicating the user's intentions.

I can only think of two situations where adding an implicit TYPE
parameter makes sense:

1. When defining locale predicates, when there are assumptions but no
value parameters.

locale count = assumes ex_inj: "EX f::'a => nat. inj f"

The locale predicate "countable" has type "'a itself => bool", which
makes sense. Currently it is also possible to make this dependence on
the type variable more explicit (although this looks a bit messy):

locale count = fixes dummy :: "'a itself" assumes ex_inj: "EX f::'a =>
nat. inj f"

But if we had something like a "fixes" clause for types, it would look
nicer and indicate the intention unambiguously, making a warning
message unnecessary:

locale count = fixes_type 'a assumes ex_inj: "EX f::'a => nat. inj f"

2. When defining constants inside locales whose right-hand sides
depend on locally-fixed type variables, the global versions of the
constants can have extra TYPE parameters.

locale count = assumes ex_inj: "EX f::'a => nat. inj f"
begin
definition unitary1 :: bool where "unitary = (ALL (x::'a) y. x = y)"
definition unitary2 :: bool where "unitary = (ALL (x::'b) y. x = y)"
end

Within the locale, we have "unitary1 :: bool", but outside the locale,
we have "count.unitary1 :: 'a itself => bool". (unitary2 has type "'b
itself => bool" inside and outside the locale.) The current locale
mechanism implements this correctly, although "unitary1" and
"unitary2" both produce the same warning message. Ideally, I think it
would be best for "unitary1" to produce no warning at all, but for
"unitary2" to be rejected with an error.

Besides these two very specific cases, I think it would be best to
reject definitions with extra type variables on the right-hand side.

- Brian



More information about the isabelle-dev mailing list