core-libraries-committee icon indicating copy to clipboard operation
core-libraries-committee copied to clipboard

Export `castWord32ToFloat`, `castFloatToWord32`, `castWord64ToDouble`, `castDoubleToWord64` from non-`GHC.*` module

Open konsumlamm opened this issue 4 months ago • 19 comments

The following functions are currently only available from GHC.Float:

They allow working on the underlying bit patterns of Floats and Doubles by providing bitcasts between Float/Double and Word32/Word64. This is not GHC-specific, so I think it makes sense to export them from a non-GHC.* module. It would also allow other Haskell compilers (like MicroHs) to provide the same module, since having to provide GHC.* modules would be awkward.

I propose exporting these functions from a new non-GHC.* module. The most obvious name would be Data.Float, but maybe someone else has a better idea.

Note: MicroHs already provides a Data.Float module, however it is only for stuff related to Float (not Double). cc @augustss

konsumlamm avatar Dec 13 '25 20:12 konsumlamm

The most obvious name would be Data.Float, but maybe someone else has a better idea.

A better idea might be to do what MicroHs does: Add Data.Float for Float and related functions (castWord32ToFloat, castFloatToWord32) and Data.Double for Double and related functions (castWord64ToDouble, castDoubleToWord64). This would also solve the problem of Float and Double having no proper home (cf. #208).

konsumlamm avatar Dec 14 '25 00:12 konsumlamm

Any opinions? @parsonsmatt @velveteer @TeofilC @Daniel-Diaz @ChickenProp @noughtmare @mpscholten @doyougnu

hasufell avatar Jan 13 '26 15:01 hasufell

I opened a draft MR, adding the new modules Data.Double (exporting Double, castWord64ToDouble, castDoubleToWord64) and Data.Float (exporting Float, castWord32ToFloat, castFloatToWord32). I'd appreciate any feedback!

konsumlamm avatar Jan 13 '26 16:01 konsumlamm

If these are really zero-cost casts then this is pinning down the exact binary layout of floats. We might want to do that, but we should do so consciously and explicitly.

noughtmare avatar Jan 14 '26 10:01 noughtmare

If these are really zero-cost casts then this is pinning down the exact binary layout of floats. We might want to do that, but we should do so consciously and explicitly.

I'd argue that already happened, since you can use Foreign to cast floats:

castD2W64 :: Double -> IO Word64
castD2W64 d = alloca $ \(p :: Ptr Double) -> poke p d >> peek (castPtr p :: Ptr Word64)

konsumlamm avatar Jan 14 '26 11:01 konsumlamm

Creative, but I think that's undefined behavior. This also passes the type checker:

castD2Bool :: Double -> IO Bool
castD2Bool d = alloca $ \(p :: Ptr Double) -> poke p d >> peek (castPtr p :: Ptr Bool)

noughtmare avatar Jan 14 '26 12:01 noughtmare

I'm not so sure this is UB, at least as long as the size and alignment match.

konsumlamm avatar Jan 14 '26 12:01 konsumlamm

Agree with noughtmare (thanks for pointing this out). Afaik nothing in GHC or the core libraries currently promises that Float and Double are represented as ieee 754 float and double. A user is free to assume that they are, and currently it'll work for them. And maybe it would be fine to promise those representations. But that feels like a GHC decision to make, I don't think the CLC should make it unilaterally.

ChickenProp avatar Jan 14 '26 12:01 ChickenProp

Note that adding the casting functions doesn't require Float and Double to be represented according to IEEE 754, it just allows users to access the internal representation..

konsumlamm avatar Jan 14 '26 12:01 konsumlamm

Converting Float to Word32 would work even if it were not IEEE754 floats. It only requires that Float is 32 bits.

augustss avatar Jan 14 '26 12:01 augustss

I foresee many people using these functions will assume IEEE754 layout. If this function does not promise IEEE754 we should be very explicit about that.

Furthermore, if we do not promise IEEE754 layout then what use are these functions? What can we safely do with the Word32 or Word64 that we couldn't do with the Float or Double? Hashing is the only use case I can come up with.

noughtmare avatar Jan 14 '26 12:01 noughtmare

Converting Float to Word32 would work even if it were not IEEE754 floats. It only requires that Float is 32 bits.

I think we don't even promise that right now. Docs: "Single-precision floating point numbers. It is desirable that this type be at least equal in range and precision to the IEEE single-precision type."

ChickenProp avatar Jan 14 '26 12:01 ChickenProp

@noughtmare

I foresee many people using these functions will assume IEEE754 layout. If this function does not promise IEEE754 we should be very explicit about that.

I think it would be a reasonable assumption, since basically everyone (including GHC and MicroHs) uses IEEE 754. I hope it would be uncontroversial for GHC to simply acknowledge the fact that it uses IEEE 754.

If we do not promise IEEE754 layout, then what use are these functions? What can we safely do with the Word32 or Word64 that we couldn't do with the Float or Double? Hashing is the only use case I can come up with.

For example, they could still be used to store Floats and Doubles in big endian or little endian format, as is done by binary and cereal. In fact, this is what gave me the inspiration for this proposal.

konsumlamm avatar Jan 14 '26 12:01 konsumlamm

as is done by binary

Oof, they already promise IEEE754 layout in their documentation.

noughtmare avatar Jan 14 '26 13:01 noughtmare

IEEE floats are the de facto standard. That was not the case 35 years ago when Haskell was defined. I think Haskell should just mandate IEEE. Other formats can use different type names.

augustss avatar Jan 14 '26 13:01 augustss

I agree acknowledging IEEE754 is the way to go, but it should probably be a concerted effort together with the GHC steering committee (and other Haskell compiler authors :P).

noughtmare avatar Jan 14 '26 13:01 noughtmare

Just to jump in here. Are there any compelling reasons not to go with IEEE? I'm not aware of really any language that doesn't.

doyougnu avatar Jan 14 '26 13:01 doyougnu

I agree acknowledging IEEE754 is the way to go, but it should probably be a concerted effort together with the GHC steering committee (and other Haskell compiler authors :P).

The concrete ask here is "GHC team OKs this and we can update docs committing to IEEE754 rep for Float and Double"?

I'm in favor

parsonsmatt avatar Jan 14 '26 22:01 parsonsmatt

Where to ask the GHC team about this? https://github.com/ghc-proposals/ghc-proposals/ ?

ChickenProp avatar Jan 15 '26 09:01 ChickenProp

I've made an issue there: https://github.com/ghc-proposals/ghc-proposals/issues/739

I don't know if a full ghc-proposal is necessary, but we can build from there.

noughtmare avatar Jan 17 '26 14:01 noughtmare