Zulip Chat Archive

Stream: general

Topic: Data.Fix and a tricky termination proof


Harry Goldstein (Dec 08 2025 at 13:21):

a Hi all. I'm playing around with a way to encode Fix for types. (I see Mathlib has Fix, but I don't think that'd work if I wanted to actually run the fixed point? I want something like Data.Fix in Haskell.) I have the following so far, which seems like it should be a good start, but there are a couple of issues:

class DataFix (fixF : Type) where
  f : Type  Type
  instFunctorF : Functor f
  instMembershipF : Membership fixF (f fixF)
  unfoldStep : fixF  f fixF
  foldStep : f fixF  fixF

def DataFix.base (fixF : Type) [DataFix fixF] : Type  Type := DataFix.f fixF

instance DataFix.instFunctorBase [DataFix fixF] : Functor (base fixF) := DataFix.instFunctorF

class LawfulDataFix (fixF : Type) extends DataFix fixF where
  unfoldStep_foldStep_id : Function.LeftInverse foldStep unfoldStep
  foldStep_unfoldStep_id : Function.RightInverse foldStep unfoldStep
  unfoldStep_size : x  unfoldStep y  sizeOf x < sizeOf y

def DataFix.fold [LawfulDataFix fixF] (alg : base fixF β  β) (x : fixF) : β :=
  (alg  Functor.map (fold alg)  unfoldStep) x
termination_by sizeOf x
decreasing_by
  -- apply LawfulDataFix.unfoldStep_size
  sorry

The first issue is that I'm not sure about the best way to say "when you call Functor.map on this, everything you find will be smaller" — I'm currently encoding it with Membership but I doubt that's correct. But there's also a more basic issue, which is that I don't actually know how to access my assumptions about fixF in the decreasing_by proof. Any advice, either about the mechanics or about the broader modeling question, would be much appreciated.

EDIT: I managed to get it to work with PFunctor, which makes a lot of sense in retrospect.


Last updated: Dec 20 2025 at 21:32 UTC