0

I am trying to write a declaration of two mutually inductive datatypes that both take a type parameter as arguments as follows:

noeq
type foo 'a =
    | FooA: x: 'a -> foo 'a
    | Foob: y: bar 'a -> foo 'a
and bar 'b =
    | BarA: x: int -> bar 'b
    | BarF: y: foo 'b -> bar 'b

I get an error message that is as follows:

LabeledStates.fst(59,0-64,31): (Error 67) Failed to solve universe inequalities for inductives 1 error was reported (see above)

(where line 59 is the line that includes "type foo 'a")

What does this error mean and what can I do to fix it?

If I remove the type parameters (and give foo.x the type of int, for example) I do not get errors anymore. Similarly, if I just give one of the types a type parameter but not the other, I also do not have errors.

1 Answers1

2

F* isn't capable of inferring universes in cases like this. You can provide explicit universe instantiations, however. For example, here are three possible solutions:

First, a doubly universe polymorphic one, most general but also possibly quite cumbersome to use

noeq
type foo (a:Type u#a) : Type u#(max a b) =
   | FooA: x: a -> foo a
   | Foob: y: bar u#b u#a a -> foo a
and bar (b:Type u#b) : Type u#(max a b) =
   | BarA: x: int -> bar b
   | BarF: y: foo u#b u#a b -> bar b

A singly universe polymorphic solution, perhaps a bit simpler, though less general:

noeq
type foo1 (a:Type u#a) : Type u#a =
   | Foo1A: x: a -> foo1 a
   | Foo1b: y: bar1 u#a a -> foo1 a
and bar1 (b:Type u#a) : Type u#a =
   | Bar1A: x: int -> bar1 b
   | Bar1F: y: foo1 u#a b -> bar1 b

And, finally, a version specialized to universe 0, probably the easiest to use if it fits your needs, but also least general:

noeq
type foo0 (a:Type u#0) : Type u#0 =
   | Foo0A: x: a -> foo0 a
   | Foo0b: y: bar0 a -> foo0 a
and bar0 (b:Type u#0) : Type u#0 =
   | Bar0A: x: int -> bar0 b
   | Bar0F: y: foo0 b -> bar0 b
Nik Swamy
  • 281
  • 1
  • 2
  • 1
    If you intend to instantiate foo and bar with relatively simple types (e.g., `int`, `bool` etc.), then I would go with the last solution `foo0, bar0`. But, if you're going to instantiate them with types like `Type` or `int -> Type` or `Type -> Type` etc. then, you may need one of the more general solutions. – Nik Swamy Jan 27 '20 at 19:11