1

When I write

codatatype inftree = node nat inftree inftree

primcorec one :: inftree and two :: inftree where
    "one = node 1 one two"
  | "two = node 2 one two"

I get

"inftree" is neither mutually corecursive with "inftree" nor nested corecursive through itself

Why, and how can I avoid it?

Joachim Breitner
  • 25,395
  • 6
  • 78
  • 139
  • My guess would be that `primcorec` only supports mutually corecursive functions for mutually corecursive datatypes, i.e. the mutual corecursion of the functions defined must precisely follow the mutual recursion of the codatatype. I don't know how to do what you are trying to do, but then again, I'm hardly an expert – one of the usual suspects w.r.t. codatatypes will probably know, but I would recommend trying the isabelle-users mailing list instead of StackOverflow. – Manuel Eberl Apr 21 '17 at 21:34
  • I was following a talk about coinduction in Coq and trying to make the point that with Isabelle, things are easy enough that I can implement it in Isabelle as the Coq talk went on … but at the point above I failed. – Joachim Breitner Apr 21 '17 at 21:54
  • If I remember correctly, Coq has codatatypes and coinduction as primitives in its logic, whereas Isabelle has to construct all of these things on top of HOL. That, of course, makes things a lot more difficult. One solution I can think of would be to introduce an artificially mutually recursive codatatype `inftree1 = node nat inftree1 inftree2` etc., define the `one` and `two` functions on it with `primcorec`, and then transfer the resulting functions to `inftree` using the obvious isomorphisms between the three types. – Manuel Eberl Apr 22 '17 at 09:23
  • Or define one function `f :: nat -> inftree` with `f n = node n (f 1) (f 2)` and define `one = f 1` and `two = f 2`… – Joachim Breitner Apr 22 '17 at 20:08

1 Answers1

2

The command primcorec supports only primitive corecursion, so mutual corecursion is only supported for mutually corecursive codatatypes. Your two functions one and two are not primitively corecursive and therefore not directly supported. If the more general command corec supported mutual corecursion, it would fall into its fragment, but mutual corecursion has not yet been implemented for corec. Therefore, you have to find a non-mutual corecursive definition and then define one and two as derived functions. The canonical solution would be to use a bool as an argument:

 primcorec one_two :: "bool => inftree" where
    "one_two is_one = Node (if is_one then 1 else 2) (one_two True) (one_two False)"

 definition "one = one_two True"
 definition "two = one_two False"

Also, you will have to generalise most properties about one and two to one_two first before you can prove them by coinduction.

Andreas Lochbihler
  • 4,998
  • 12
  • 10