3

First, without knowing much about type classes, it appears that type classes are the best way to overload notation for a type, unless I can't use type classes, or haven't figured out how. I'm not using type classes.

Second, I'm pretty sure that I don't want to override notation for operators that have meaning for all types, such as \<in>, \<times>, *, \<union>, etc.

However, an operator such as + has no meaning for my type sT, though this ties back into my first point. I eventually would like + to have multiple meanings for type sT => sT => sT, which, I would think, is not going to happen.

Four versions of an example

To make my question specific and show that I'm not the only one with the problem, I take a simple example from Klein's course, the file being Demo14.thy.

After four versions of the example, I ask, "For the fourth example, can I get rid of the warnings?"

He starts with a simple example which gives no warnings or errors:

locale semi =
  fixes prod :: "['a, 'a] => 'a" (infixl "\<cdot>" 70)
  assumes assoc: "(x \<cdot> y) \<cdot> z = x \<cdot> (y \<cdot> z)" 

He uses \<cdot>, and this represents what I've been doing so far, not using notation that has already been claimed by Isabelle/HOL.

I change his \<cdot> to +, and I get an error:

locale semi2 =
  fixes prod :: "['a, 'a] => 'a" (infixl "+" 70)
  assumes assoc: "(x + y) + z = x + (y + z)"

Having looked at the HOL sources, I've seen that + has been defined for type ('a => 'a => 'a), in particular, for certain type classes.

I modify semi2 to make sure it's not specific to 'a alone, and I then only get warnings:

locale semi3 =
  fixes prod :: "('a => 'a) => ('a => 'a) => 'a" (infixl "+" 70)
  assumes assoc: "(x + y) + z = x + (y + z)"

What I really care about is this fourth version, which gives a warning, even though I've inserted (x::sT):

locale semi4 =
  fixes prod :: "sT => sT => sT" (infixl "+" 70)
  assumes assoc: "((x::sT) + y) + z = x + (y + z)"

The warning is:

Ambiguous input
produces 16 parse trees (10 displayed):
[...]
Fortunately, only one parse tree is type correct,
but you may still want to disambiguate your grammar or your input.

Summary and question

For myself, I summarize it like this: The operator + has been defined in many places, and in particular for type 'a => 'a => 'a, which also in general defines it for sT => sT => sT. Because of that, the prover does a lot of work, and after finally figuring out that my semi4 is the only place that + has been defined for type sT => sT => sT, it lets me use it.

I don't know about my summary, but can I fix semi4 so that it doesn't give me a warning?

(Note: Given the example, mathematically it would make more sense to use the symbol * instead of +, but * would be notation that I wouldn't want to override.)

1 Answers1

1

I think I've figured most of it out.

Suppose you have a function

myFun :: "myT => myT => myT", 

and you want to use the plus symbol + as notation.

The key is the context in which + is defined. At the global level, there are at least two ways. One is the simple way

myFun (infixl "+" 70)

Another way is defining + in a type class definition. In particular, in Groups.thy, at line 136 are the two lines

class plus =
  fixes plus :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"  (infixl "+" 65)

So, with that preface, the short answer is that at the global level, there's only one way to get rid of the warnings when trying to use + for myFun :: "myT => myT => myT", and that is to instantiate type myT as type class plus for the function myFun.

Doing that is very simple, where I will show how to do it, and it's independent of all the locales and additional classes in Groups.thy that use plus.

However, after defining type myT at the global level, whether through the simple way or through type classes, trying to define + again for type (myT => myT => myT) will cause an error both at the global level, and in locales.

It makes sense now. The use of overloaded syntax is all based on type inference, so a specific syntax for a specific type can only be assigned to one function.

For locales, the use of + in different locales is independent. The cause of the warnings is because of the type class definition plus. You can't get rid of the warning for locales because plus has been defined as a type class for ('a => 'a => 'a), which is a global definition.

Here's some code with some comments in it. Instantiating plus for myT takes all of 5 lines.

  typedecl myT

--"Two locales can both use '+'. The warning is because '+' has been defined
   in a type class for 'a. If anything defines '+' globally for type myT, these
   locales will give an error for trying to use it."
locale semi1 =
  fixes plus :: "myT => myT => myT" (infixl "+" 70)
  assumes assoc: "((x::myT) + y) + z = x + (y + z)"
locale semi2 =
  fixes plus :: "myT => myT => myT" (infixl "+" 70)
  assumes assoc: "((x::myT) + y) + z = x + (y + z)"


--"DEFINING PLUS HERE GLOBALLY FOR (myT => myT => myT) RESERVES IT EXCLUSIVELY"

definition myFun :: "myT => myT => myT" (infixl "+" 70) where
  "myFun x y = x"
--"Use of 'value' will give a warning if '+' is instantiated globablly prior
   to this point."
value "(x::myT) + y"


--"PLUS HAS BEEN DEFINED ALREADY. SWITCH THIS NEXT SECTION WITH THAT ABOVE AND
    myFun THEN GETS THE ERROR. DELETE myFun AND THE ERROR GOES AWAY."

definition myT_plus_f :: "myT => myT => myT" where
  "myT_plus_f x y = x"

instantiation myT :: plus
begin
  definition plus_myT:
    "x + y = myT_plus_f x y"  --"Error here if '+' globally defined prior to this for type myT."
  instance ..
end
--"No warning here if '+' instantiated for myT; error if '+' defined globablly for
   type myT."
value "(x::myT) + y"


--"ERRORS HERE FOR LOCALES BECAUSE '+' IS DEFINED GLOBALLY"

locale semi3 =
  fixes plus :: "sT => sT => sT" (infixl "+" 70)
  assumes assoc: "((x::sT) + y) + z = x + (y + z)"
locale semi4 =
  fixes plus :: "sT => sT => sT" (infixl "+" 70)
  assumes assoc: "((x::sT) + y) + z = x + (y + z)"