Zulip Chat Archive

Stream: lean4

Topic: Bool from LT/LE


Joscha Mennicken (Dec 17 2021 at 21:13):

Comparing numbers like a < b && c <= d seems to result in a Bool, but after implementing LT, LE and Ord for a structure, lean complains that a < b is a Prop and not a Bool. However, there don't seem to be BLe or BLt classes like with BEq. When does this automatic conversion between Prop and Bool work?

Chris B (Dec 17 2021 at 21:23):

There are two coercions, one from Bool to Prop and one from Decidable Props to Bool

Joscha Mennicken (Dec 17 2021 at 21:27):

So I would need an instance (a b : MyStructure) : Decidable (a < b) (and the same for <=) in addition to my LT and LE instances to be able to use these comparisons in code

Henrik Böving (Dec 17 2021 at 21:30):

Yes, in general if then else statement can do a decision based on any proposition that implements the Decidable type class (either directly or through TC synthesis)

Chris B (Dec 17 2021 at 21:32):

If you're working with a structure and the fields implement DecidableEq and Ord, you can derive them for your new structure:

structure X where
  val : Nat
deriving DecidableEq, Ord

And Ord gets you instances of LT and LE.

Joscha Mennicken (Dec 17 2021 at 21:39):

Ah, ltOfOrd and leOfOrd give me the appropriate Decidable instances as a bonus

Nicolas Rouquette (Jul 31 2022 at 04:12):

I have a related question: how do I require an instance of Decidable for a comparison?

Here is a simple example:

import Std.Data.HashSet
open Std

-- Question: Can this be generalized to a HashSet of α if there is LT.lt α?
instance : Repr (HashSet String) where
  reprPrec hs _ :=
    let as : Array String := hs.toArray.qsort (fun a b => a < b)
    as.toList.toString

instance [comp: LT α] [Decidable comp.lt] [ToString α] [Inhabited α] [BEq α] [Repr α] [Hashable α]: Repr (HashSet α) where
  reprPrec hs x :=
    let as : Array α := hs.toArray.qsort (fun a b => a < b)
    as.toList.toString

This has two errors:

  • [Decidable comp.lt] seems the wrong syntax to require a decidable comparison.
  • The sort predicate is a Prop, not a Bool

How do I fix this?

François G. Dorais (Jul 31 2022 at 04:44):

There's a couple of common patterns:

  • [LT α] [DecidableRel (α:=α) (.<.)]
  • [LT α] [DecidableRel (.<. : α → α → Prop)]
  • [LT α] [DecidableRel (@LT.lt α)]

Also consider using [Ord α] instead.

Nicolas Rouquette (Jul 31 2022 at 18:29):

Thanks @François G. Dorais !

I managed to make this work with all the patterns you suggested!

import Std.Data.HashSet
open Std

-- Question: Can this be generalized to a HashSet of α if there is LT.lt α?
instance : Repr (HashSet String) where
  reprPrec hs _ :=
    let as : Array String := hs.toArray.qsort (fun a b => a < b)
    as.toList.toString

instance [LT α] [DecidableRel (α:=α) (.<.)] [ToString α] [Inhabited α] [BEq α] [Repr α] [Hashable α]: Repr (HashSet α) where
  reprPrec hs _ :=
    let as : Array α := hs.toArray.qsort (.<.)
    as.toList.toString

instance [LT α] [DecidableRel (.<. : α  α  Prop)] [ToString α] [Inhabited α] [BEq α] [Repr α] [Hashable α]: Repr (HashSet α) where
  reprPrec hs _ :=
    let as : Array α := hs.toArray.qsort (.<.)
    as.toList.toString

instance [lt: LT α] [DecidableRel lt.lt] [ToString α] [Inhabited α] [BEq α] [Repr α] [Hashable α]: Repr (HashSet α) where
  reprPrec hs _ :=
    let as : Array α := hs.toArray.qsort (.<.)
    as.toList.toString

instance [LT α] [ord:Ord α] [ToString α] [Inhabited α] [BEq α] [Repr α] [Hashable α]: Repr (HashSet α) where
  reprPrec hs _ :=
    let as : Array α := hs.toArray.qsort (fun a b => ord.compare a b == Ordering.lt)
    as.toList.toString

The last one above seems to me like a TC bad smell since(fun a b => ord.compare a b == Ordering.lt) is clearly a duplication of Lean's TC instance:

instance [Ord α] : DecidableRel (@LT.lt α ltOfOrd) :=
  inferInstanceAs (DecidableRel (fun a b => compare a b == Ordering.lt))

Is there a TC instantiation trick that would help avoid this unnecessary duplication?


Last updated: Dec 20 2023 at 11:08 UTC