4

this is a beginner question.

I am going through the tutorial "Programming and Proving in Isabelle/HOL".

I want to print the result of "1 + 2".

So I wrote:

value "1 + 2"

Which gives:

"1 + (1 + 1)"
 :: "'a"

I would like to see the result, i.e., "3". How can I do that in Isabelle? If I normalize "1+2" in the theorem prover, the result 3 is displayed. I just want to do the same in Isabelle.

Please mind, I started using Isabelle yesterday.

chris
  • 4,988
  • 20
  • 36
mrsteve
  • 4,082
  • 1
  • 26
  • 63

2 Answers2

10

In Isabelle, integer literals (also called numerical constants) like ..., -2, -1, 0, 1, 2, ... are overloaded.

There are type classes for zero (zero), one (one), positive numerals (numeral), and negative numerals (neg_numeral). The latter two also incorporate type classes for the additive semi-group (semigroup_add) -- allowing for the use of + -- and the additive group (group_add) -- allowing for the use of + and - (also unary) -- respecively. (Also note that the plus sign itself (op +) is overloaded in class plus.)

Now, if you enter an expression, Isabelle infers the most general type. Often this is more general than one expects. This is exactly what you encountered. Consider some examples:

input      inferred type      type class
 0           'a                 'a::zero
 1           'a                 'a::one
 op +        'a => 'a => 'a     'a::plus
 1 + 2       'a                 'a::numeral
 x + y       'a                 'a::plus
 Suc 0 + y   nat                (nat is an instance, among others,
                                of class semigroup_add)

In such a situation you can tell the system that you mean a less general type by explicitly adding a type constraint, e.g., (1::nat) + 2 results in the overall type nat.

If you use Isabelle/jEdit you can investigate such situations conveniently without introducing noise like declare [[...]] in your theory. For example when entering

value "1 + 2"

in the Output panel you see

"1 + (1 + 1)"
  :: "'a"

Now you can Ctrl-click (i.e, keep the control button pressed and click with the mouse) on the 'a in the output. Which will tell you that 'a is in class numeral. You can further Ctrl-click numeral to get to the definition of this type class.

If you change your input to (for natural numbers)

value "(1::nat) + 2"

or (for integers)

value "(1::int) + 2"

the output will be

"Suc (Suc (Suc 0)))" :: "nat"

and

"3" :: "int"

as expected.

Update: Note that natural numbers (type nat) will be printed in unary representation like: 0, Suc 0, Suc (Suc 0), ... . This is not to be confused with 1 + (1 + (1 + ...)) however (which is of arbitrary type of class numeral). Such "Peano numbers" constitute proper natural numbers, as if nat was defined as follows:

datatype nat = 0 | Suc nat

So this is merely about pretty-printing, but logically irrelevant.

chris
  • 4,988
  • 20
  • 36
  • I write `value "(8 :: nat) + (3 :: nat)"` but I still see the output as "Suc (Suc (Suc...". Any idea why? I am using Isabelle2015 – Martin Copes Dec 25 '15 at 15:01
4

This is my kind of question. One beginner to another, how fortunate.

I don't know all the details, but when you don't specify the type for your constants 1 and 2, then you're working with a numeral, which is all laid down in Num.thy.

Try this and look in the output panel:

declare[[show_consts=true]]
declare[[show_types=true]]
declare[[show_sorts=true]]
value "1 + 2"
value "1 + (2::nat)"

theorem "1 + 2 = z"
  apply simp
  oops

You'll see that 1+2 is numeral, and doesn't get simplified automatically, or rather, get's simplified too much by being expanded into the "successor" form of addition.

The value "1 + (2::nat)" does get simplified to the "preferred human form".

After simp, the 1 + 2 does get simplified to the "preferred form" even though it's numeral.

  • 1
    This might be nitpicking ;), but `1` on its own actually is of class `one` not `numeral`. The reason why `1 + 2` is of type `'a::numeral` is that `2`, as you said, is of class `numeral`. But, e.g., `1 + 1` has type `'a::{one,plus}` (i.e., `'a` is an instance of both type classes `one` and `plus`). – chris May 20 '13 at 03:35
  • @chris, nitpicking's okay. Not being aware of subtleties can be deadly. What you say is a reminder. I've seen that 0 and 1 are special. I had to prove some extra things about them for some nat stuff. However, Num.thy has been on my mind because I've seen lately that lots of things get filtered through num and numeral. Num.thy works some good magic. Say thanks to Haftman and Huffman when you see them, considering it's a Isa2012 addition. Mrsteve, if you're inclined, I suggest you switch your accepted answer from mine to Chris', so his is first. His is more complete. –  May 20 '13 at 04:36