Zulip Chat Archive
Stream: Type theory
Topic: Is there mutually recursive classes?
Tesla Zhang (Feb 03 2023 at 02:45):
Hi, this is a beginner question. Does Lean4 classes support mutual recursion? If so, does that always imply mutually recursive instances, and is there any obvious problems regarding mutual recursion in classes?
Apart from that, is there mutual recursion between classes & functions/inductives?
Mario Carneiro (Feb 03 2023 at 02:46):
No, classes cannot be recursive at all
Mario Carneiro (Feb 03 2023 at 02:46):
more specifically, structure
cannot
Mario Carneiro (Feb 03 2023 at 02:46):
class
is just @[class] structure
Tesla Zhang (Feb 03 2023 at 02:47):
I see, thank you very much! That's a fast and furious reply.
Mario Carneiro (Feb 03 2023 at 02:47):
you can use class inductive
and those can be recursive
Tesla Zhang (Feb 03 2023 at 02:47):
??????????? How does class inductive
work? What does it mean?
Mario Carneiro (Feb 03 2023 at 02:47):
@[class] inductive
Tesla Zhang (Feb 03 2023 at 02:48):
What do implementers implement? Constructing the instances? Is it useful in any scenarios?
Mario Carneiro (Feb 03 2023 at 02:48):
@[class]
is just a signal to the typeclass inference mechanism that this type can be used in []
and inferred by tc inference by default
Tesla Zhang (Feb 03 2023 at 02:48):
Ok, I see, that's very intuitive
Mario Carneiro (Feb 03 2023 at 02:48):
similarly instance
is just @[instance] def
Mario Carneiro (Feb 03 2023 at 02:48):
so you can also just make elements of that inductive and mark them as instances
Tesla Zhang (Feb 03 2023 at 02:48):
Ok, great da★ze
Mario Carneiro (Feb 03 2023 at 02:49):
The graph of instances doesn't have to mirror the definitions at all, it can have loops and whatnot (but you might hit issues if the instances are set up badly)
Tesla Zhang (Feb 03 2023 at 02:50):
I see, I guess I can find the rest of the answers in tabled typeclass resolution, right? Thanks again!
Mario Carneiro (Feb 03 2023 at 02:50):
it's just like a bunch of theorems saying given an A and a B you get a C and so on, and the TC inference mechanism just applies these eagerly
Mario Carneiro (Feb 03 2023 at 02:51):
that paper describes how it is able to present this interface without performance problems, it is not particularly relevant for users except insofar as it determines what kinds of patterns cause TC inference to fall over
Mario Carneiro (Feb 03 2023 at 02:52):
I think it is intended for implementers, e.g. if you wanted to write a TC inference implementation for another language
Tesla Zhang (Feb 03 2023 at 02:53):
Yeah, I am currently implementing classes for a theorem prover like Lean, and I'm thinking about mutual recursion support for classes.
The language has fancy inference for mutual recursions. You write them down like in Java and it'll be type checked with inferred orders. Compared to this, Coq & Agda are like C/C++ where we need forward declarations :) I'm unsure what Lean4 does though
Mario Carneiro (Feb 03 2023 at 02:54):
ah, in that case it is indeed the paper to read
Mario Carneiro (Feb 03 2023 at 02:55):
I believe it comes down to better caching support to help detect loops
Mario Carneiro (Feb 03 2023 at 02:55):
there are some simple patterns that lead to exponential behavior if you aren't careful with caching
Tesla Zhang (Feb 03 2023 at 02:57):
Yeah I can see that happening in Haskell/Agda
Mario Carneiro (Feb 03 2023 at 02:58):
In your description it is not clear whether you are talking about the typeclass inference mechanism (like in haskell) or recursive functions, where at run time functions call each other in a loop
Mario Carneiro (Feb 03 2023 at 02:59):
Coq / Agda / Lean all have to be very strict about recursive functions because you can prove false if you don't have a clear well founded metric
Mario Carneiro (Feb 03 2023 at 02:59):
for typeclass inference you can basically have an arbitrary graph of dependencies because everything is resolved at compile time
Mario Carneiro (Feb 03 2023 at 03:02):
Most programming languages are less strict about recursive functions, and allow arbitrary call graphs (possibly with forward declarations) because they aren't trying to prevent partiality
Tesla Zhang (Feb 03 2023 at 03:11):
I'm talking about the definition of classes and instances and its language-feature-interaction with termination check. I've heard of some bad stories so I'm a little worried :(
Tesla Zhang (Feb 03 2023 at 03:13):
Specifically, if you define the instance Show where show x = ?
(I hope the idea is clear) for, say, inductive X := A : X | B : List X -> X
, you'll end up invoking instance [Show X] => Show (List X)
which is involved in the call graph and the termination check needs it to figure out the structural recursion-ness of the definition, while this is not clear simply by resolving the names
Last updated: Dec 20 2023 at 11:08 UTC