Zulip Chat Archive

Stream: general

Topic: How to make a function that accepts only positive Float?


Mykhailo Dm (Dec 19 2024 at 18:18):

For example, i would like to write a log function that accepts only positive Float as a base.

Riccardo Brasca (Dec 19 2024 at 18:28):

You can specify the domain of a function to be any type you want. But note that if f it is defined on positive real numbers and x is a real number that you know to be positive, then f x does not make sense (there are ways to make it work in a certain sense, but it is annoying). The usual solution is to define f x for any x, using a junk value in the non positive case.

Jireh Loreaux (Dec 19 2024 at 18:30):

import Lean

def Float.log' (x : {x : Float // 0 < x}) : Float := x.1.log

/- Lean complains here that:

unused variable `hx`
note: this linter can be disabled with `set_option linter.unusedVariables false`-/
def Float.log'' (x : Float) (hx : 0 < x) : Float := x.log

Riccardo Brasca (Dec 19 2024 at 18:30):

It's probably a good idea to read this https://xenaproject.wordpress.com/2020/07/05/division-by-zero-in-type-theory-a-faq/

Jireh Loreaux (Dec 19 2024 at 18:31):

But yes, I agree with Riccardo, you probably just want Float.log (espcially because you can't prove anything about Float since it is opaque.

Mykhailo Dm (Dec 19 2024 at 18:46):

Jireh Loreaux said:

import Lean

def Float.log' (x : {x : Float // 0 < x}) : Float := x.1.log

/- Lean complains here that:

unused variable `hx`
note: this linter can be disabled with `set_option linter.unusedVariables false`-/
def Float.log'' (x : Float) (hx : 0 < x) : Float := x.log

Trying to #eval any of these (#eval Float.log' (10.)) with both positive and negative values gives me an errors. Am I doing something wrong here or i have to call them somehow a bit in a special way?

Kyle Miller (Dec 19 2024 at 18:52):

These expect a proof that 10 is positive. That is, you need to put something in place of sorry here:

#eval Float.log'' 10.0 (by sorry)

However, like Jireh said, Float is opaque, so this isn't something that can be proved, as far as I know.

Kyle Miller (Dec 19 2024 at 18:54):

If you are OK with trusting the Lean compiler as part of the trusted code base, you can use native_decide to calculate that it is in bounds:

#eval Float.log'' 10.0 (by native_decide)

Kyle Miller (Dec 19 2024 at 18:54):

native_decide uses the runtime characteristics of Float rather than any theoretical specification

Mykhailo Dm (Dec 19 2024 at 19:12):

Kyle Miller said:

If you are OK with trusting the Lean compiler as part of the trusted code base, you can use native_decide to calculate that it is in bounds:

#eval Float.log'' 10.0 (by native_decide)

Yay, it works, thanks!! But this isn't "compile time", right?

Kyle Miller (Dec 19 2024 at 19:22):

by native_decide is a compile-time check. It only works for compile-time constants. (More specifically, it is "elaboration time" in Lean terminology)

It's possible to do run-time checking too, using a different method (if h : ... then ... else ... syntax)


Last updated: May 02 2025 at 03:31 UTC