Zulip Chat Archive

Stream: general

Topic: instance of `HPow Float Nat` doesn't exist


Asei Inoue (Apr 06 2024 at 07:59):

why?

variable (f : Float) (n : Nat)

#check_failure f ^ n

Asei Inoue (Apr 06 2024 at 08:01):

spinylobster suggest to add a following code. How about this?

instance [ n, OfNat α n] [HPow α α α] : HPow α Nat α where
  hPow x n := x ^ (OfNat.ofNat n : α)

#eval 0.1 ^ 2

Julian Berman (Apr 06 2024 at 11:57):

Doesn't that #evalwork even without the instance? Specifically it looks like there already is an OfNat for Float.

Julian Berman (Apr 06 2024 at 12:00):

I don't really know what the norms are but I guess I'm slightly surprised (in a "I don't know what I'm doing so probably there's a reason but I wouldn't have guessed this" sense) that 1) HPow doesn't look for a coercion instance and use it in general and 2) there actually is no coercion instance from Nat to Float (besides the OfNat there's Nat.toFloat but it's not a Coe. That coercion is lossy obviously, so maybe that's the reason it's not marked Coe, or maybe that just wasn't useful for anything, or...)

Eric Wieser (Apr 06 2024 at 12:37):

That use of OfNat isn't legal, you're only supposed to use it for numeric literals

Eric Wieser (Apr 06 2024 at 12:37):

It surpriseds me that we have both docs#Nat.toFloat and docs#Float.ofNat

Julian Berman (Apr 06 2024 at 12:49):

The former is just an alias, yeah? Maybe just for discoverability?

Asei Inoue (Apr 06 2024 at 13:07):

@Eric Wieser You say this is not legal?

#check_failure f ^ n

instance [ n, OfNat α n] [HPow α α α] : HPow α Nat α where
  hPow x n := x ^ (OfNat.ofNat n : α)

#check f ^ n

Julian Berman (Apr 06 2024 at 13:15):

I thought Eric was right too but I see some other instances where OfNat _ n n is not some honest-to-goodness natural number literal?

Julian Berman (Apr 06 2024 at 13:15):

E.g. core has... instance : OfNat JsonNumber n := ⟨JsonNumber.fromNat n⟩

Julian Berman (Apr 06 2024 at 13:17):

And a few others which are very similar it looks like?

Julian Berman (Apr 06 2024 at 13:18):

Oh right and the OfNat for Float itself of course... instance : OfNat Float n := ⟨Float.ofNat n⟩

Julian Berman (Apr 06 2024 at 13:19):

Oh sorry, but I misunderstood Eric's message, yeah, that was similar to what I was trying to say too by pointing out the instance you defined isn't needed. Basically OfNat is only if you're going to write ^ 2, not if you have ^ n and n is a variable.

Asei Inoue (Apr 06 2024 at 13:30):

Basically OfNat is _only_ if you're going to write ^ 2, not if you have ^ n and n is a variable.

I see. I understand the meaning of the message.

Asei Inoue (Apr 06 2024 at 13:36):

Ok this works.

variable (f : Float) (n : Nat)

#check_failure f ^ n

instance : HPow Float Nat Float where
  hPow a b := a ^ b.toFloat

#check f ^ n

My point was why this instance is not included in Std or Mathlib.

Eric Wieser (Apr 06 2024 at 13:37):

I think you're supposed to work with floats everywhere in the first place

Eric Wieser (Apr 06 2024 at 13:37):

Mixing infinite precision nats and lossy floats is a bit weird

Yury G. Kudryashov (Apr 14 2024 at 04:41):

The generic instance above will create a diamond, e.g., for Real. As for Float, one may want to have an instance implemented in C/C++ that uses nat-specific pow in case the number is not a long number.

Yury G. Kudryashov (Apr 14 2024 at 04:43):

Or should it work with types like UInt64 instead?

Kyle Miller (Apr 14 2024 at 19:18):

Elaboration for ^ is fiddly, and you have to be very careful with global instances. The issue is that we're trying to make it so that when, for example, x y : Real, then x ^ 2 gives the HPow Real Nat Real instance but x ^ y gives the HPow Real Real Real instance.

Regarding Float instances, I just made sure that the homogeneous Pow Float instance worked.

I don't see a problem with including that specific HPow Float Nat Float instance. You just have to be aware that (3 : Float) ^ 2 will still elaborate with 2 : Float.


Last updated: May 02 2025 at 03:31 UTC