Zulip Chat Archive
Stream: lean4
Topic: Refine type
eduardo (May 29 2024 at 23:27):
I'm trying to encode refinement types through evidence, like NonEmptyString; I've found an older conversation with an example, but simp
is not solving the goal.
https://leanprover-community.github.io/archive/stream/270676-lean4/topic/newtype.html
The closest result I've reached is this one.
structure NonEmptyString where
value : String
ev : value.length > 0
deriving Repr
def mkNonEmptyString (s : String) (ev : s.length > 0) : NonEmptyString :=
{ value := s, ev := ev }
def eg : NonEmptyString :=
mkNonEmptyString "hello" (by decide)
Is it possible to pin a tactic into mkNonEmptyString
and avoid applying it manually in the callers?
Chris Bailey (May 29 2024 at 23:30):
Indeed it is.
def mkNonEmptyString (s : String) (ev : s.length > 0 := by decide) : NonEmptyString :=
{ value := s, ev := ev }
def eg : NonEmptyString :=
mkNonEmptyString "hello"
eduardo (May 29 2024 at 23:35):
Thank you, Chris!
eduardo (May 29 2024 at 23:35):
Can I take this opportunity to ask you what the semantic difference is between defining the evidence in the signature instead of within the function? I saw some examples, but they don't work (at least for this tactic).
def mkNonEmptyString (s : String) : NonEmptyString :=
let ev : s.length > 0 := by decide
{ value := s, ev := ev }
Eric Wieser (May 29 2024 at 23:37):
def mkNonEmptyString (s : String) : NonEmptyString :=
amounts to claiming that all strings are non-empty, which is obviously false!
Eric Wieser (May 29 2024 at 23:38):
(ev : s.length > 0 := by decide)
is a hint to the caller; it's a regular argument, but if the caller omits it asmkNonEmptyString "hello"
then it is elaborated as mkNonEmptyString "hello" (by decide)
eduardo (May 29 2024 at 23:40):
Thank you, Eric!
Chris Bailey (May 29 2024 at 23:40):
If it helps, that syntax (a : A := ..)
is generic syntax for an optional argument, it just happens to work with proofs (and proofs via tactic):
def foo (a : Nat) (b : Nat := 0) : Nat := a + b
#eval foo 10 -- 10
#eval foo 10 5 -- 15
Markus Schmaus (May 30 2024 at 20:16):
You can also provide a default when defining structure
, and you don't need to define an extra mkNoneEmptyString
, since NonEmptyString.mk
already exists. With this your example becomes:
structure NonEmptyString where
value : String
ev : value.length > 0 := by decide
deriving Repr
def eg : NonEmptyString :=
NonEmptyString.mk "hello"
eduardo (May 30 2024 at 22:12):
Hmm, it seems https://leanprover-community.github.io/archive/stream/270676-lean4/topic/newtype.html is correct except for the tactic; it wasn't clear to me if we were allowed to have default tactics at the structure declaration level. The compiler generates the mk
I was looking for. Thank you, Marcus!
Last updated: May 02 2025 at 03:31 UTC