1

I'm wondering, is it possible to have records whose values depend on each other, without being recursively defined in terms of types? Basically, I have a record type that looks like this:

record SomeRec (a : Set) : Set where   
  method1 : a -> a -> Foo   
  method2 : a -> a -> Bar  
  ...  
  method n : a -> a -> Baz

where n is large enough that I want to actually bundle all of these up as records, instead of just having a bunch of mutually recursive functions. (Also, I'm using SomeRec as an instance argument). Notably, SomeRec is not recursive: none of its fields types refer to SomeRec.

Right now, I have a Description D, where FD : Set -> Set is the functor described by D. What I'm trying to show is the following:

 

muRec : ( FRec : (a : Set) -> SomeRec a -> SomeRec (FD a) ) -> SomeRec (mu D)

That is, if I can take a (SomeRec a) to a (SomeRec (F a)), then I can tie the knot recursively and show the instance for the whole thing. In principle this can be done: each recursive call to a field of SomeRec would happen with strictly smaller arguments. If I were to just have 10 mutually recursive methods, it would work. But if I try to build the record, I end up passing muRec to FRec without its arguments decreasing.

So, what I'm wondering is: is there a way to show that this is well-founded? Can induction or coinduction help, even though the record type is not inductive or coinductive?

My current approach is to make a size-indexed version of D, and build SomeRec for size n out of SomeRec for size < n. But this is dramatically increasing the complexity of what I'm doing, and I'm having to use Brouwer ordinals to get size bounds on what I'm doing. So I'm wondering if there's a better way.

Thanks!

jmite
  • 8,171
  • 6
  • 40
  • 81

1 Answers1

2

The FRec : (a : Set) -> SomeRec a -> SomeRec (FD a) argument is asking for too much. It shouldn't be asking for a full SomeRec a, but rather only for the results of calling those methods on the subterms of some x : FD a.

If the methods are really simply typed you could instead define

record Results : Set where   
  field1 : Foo   
  field2 : Bar  
  ...  
  fieldn : Baz

Then have muRec have a type like

muRec : (FRec : (a : Set) (x : FD a) (y : FD a) 
                 (IH : (t1 t2 : a) -> In t1 x -> In t2 y -> Results)
                 -> Results)
        -> mu D -> mu D -> Results

The type of IH might need to be adjusted depending on your recursion pattern. And In : {a : Set} -> a -> FD a -> Set is some predicate you should be able to define by using D, which should relate subtrees to their parent.

Saizan
  • 1,391
  • 8
  • 4