Rust’s type system is based on algebraic data types, which results in being able to take ‘unit’, ‘product’ and ‘sum’ and construct any other time. This implies that fundamentally, a structural equivalence should be done at this level, in theory. If structurally equivalent types aren’t actually equivalent, that has to be due to a ‘user’ defined operation which understands more information and makes the distinction. The same is true for the opposite, structurally nonequivalent types that are actually equivalent.

The following program, while somewhat silly, does demonstrate that Rust is inconsistent in how it applies pattern matching, when considering primitive types vs user defined types. Fundamentally, a f64 is a u64 with different operations. Rusts documentation suggests that the reason for this is because f64 and u64 have different impls of `PartialEq`

(https://doc.rust-lang.org/stable/std/primitive.f64.html).

```
#[derive(Debug)]
struct Float {
value: u64,
}
impl std::cmp::PartialEq for Float {
fn eq(&self, other: &Float) -> bool {
unsafe {
let a: f64 = std::mem::transmute(self.value);
let b: f64 = std::mem::transmute(other.value);
a == b
}
}
}
fn main() {
{
const P0: f64 = 0.0;
const N0: f64 = -0.0;
// Positive 0 and negative 0 are equal.
assert_eq!(P0, N0);
let p0: u64 = unsafe { std::mem::transmute(P0) };
let n0: u64 = unsafe { std::mem::transmute(N0) };
// Positive 0 and negative 0 have different structure.
assert!(p0 != n0);
// Constants + Pattern matching should let me compare something structurally.
// Therefore, these should be different.
match N0 {
P0 => println!("equal"),
_ => println!("not equal"),
}
}
{
const P0: Float = Float { value: 0 };
const N0: Float = Float { value: 9223372036854775808 };
// Positive 0 and negative 0 are equal.
assert_eq!(P0, N0);
let p0: u64 = unsafe { std::mem::transmute(P0) };
let n0: u64 = unsafe { std::mem::transmute(N0) };
// Positive 0 and negative 0 have different structure.
assert!(p0 != n0);
// Constants + Pattern matching should let me compare something structurally.
// Therefore, these should be different.
match N0 {
P0 => println!("equal"),
_ => println!("not equal"),
}
}
}
```

Output:

```
equal
not equal
```

So, my fundamental question is, why can’t I implement a float that behaves like a float? And if pattern matching should be structural, why does it currently use `PartialEq`

for floats, rather than bit-wise equality?