digitalmars.D - Floating point in the type system
- Robert (24/24) Sep 12 2015 Hi all,
- Atila Neves (3/27) Sep 12 2015 What do think is unusual?
- Robert (7/43) Sep 12 2015 It's unusual, because `float.nan != float.nan`, so one might
- Xinok (6/17) Sep 12 2015 (1) f = f2; // This is assignment, not comparison
- anonymous (19/25) Sep 12 2015 I don't know what the compiler actually does, but it looks like the
- Ola Fosheim Grostad (4/7) Sep 12 2015 Types need to mangle to the same name, but using floats in a type
- Robert (9/15) Sep 12 2015 For what it's worth, I was investigating this initially as a
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (6/9) Sep 12 2015 C++ does not allow it. And frankly, having more than a single
- "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= (12/15) Sep 12 2015 I don't know Idris, but you can't easily unify over floats,
Hi all, I came across this example, and wondered what your thoughts on it are: ``` void main(string[] args) { struct Foo(float f) { alias VAL = f; float getF() { return f; } } Foo!(float.nan) f; Foo!(float.nan) f2; // This will fail at compile time static assert(f.VAL == f2.VAL); // This will fail at run time assert(f.getF() == f2.getF()); // But this is ok f = f2; } ``` It seems a little unusual to me. Robert
Sep 12 2015
On Saturday, 12 September 2015 at 15:13:27 UTC, Robert wrote:Hi all, I came across this example, and wondered what your thoughts on it are: ``` void main(string[] args) { struct Foo(float f) { alias VAL = f; float getF() { return f; } } Foo!(float.nan) f; Foo!(float.nan) f2; // This will fail at compile time static assert(f.VAL == f2.VAL); // This will fail at run time assert(f.getF() == f2.getF()); // But this is ok f = f2; } ``` It seems a little unusual to me. RobertWhat do think is unusual? Atila
Sep 12 2015
On Saturday, 12 September 2015 at 15:49:23 UTC, Atila Neves wrote:On Saturday, 12 September 2015 at 15:13:27 UTC, Robert wrote:It's unusual, because `float.nan != float.nan`, so one might expect that `typeof(Foo!(float.nan) != Foo!(float.nan))`, whereas this is clearly not the case, even with both the static assert and runtime assert failing. I'm just curious to understand the reasoning behind this, whether it's intentional, and whether it matters at all.Hi all, I came across this example, and wondered what your thoughts on it are: ``` void main(string[] args) { struct Foo(float f) { alias VAL = f; float getF() { return f; } } Foo!(float.nan) f; Foo!(float.nan) f2; // This will fail at compile time static assert(f.VAL == f2.VAL); // This will fail at run time assert(f.getF() == f2.getF()); // But this is ok f = f2; } ``` It seems a little unusual to me. RobertWhat do think is unusual? Atila
Sep 12 2015
On Saturday, 12 September 2015 at 16:08:31 UTC, Robert wrote:On Saturday, 12 September 2015 at 15:49:23 UTC, Atila Neves wrote:(1) f = f2; // This is assignment, not comparison (2) alias VAL = f; // This is not a data member so is not involved in comparisons or assignments change "alias VAL" to "float VAL" and then you might see the behavior you expect.What do think is unusual? AtilaIt's unusual, because `float.nan != float.nan`, so one might expect that `typeof(Foo!(float.nan) != Foo!(float.nan))`, whereas this is clearly not the case, even with both the static assert and runtime assert failing. I'm just curious to understand the reasoning behind this, whether it's intentional, and whether it matters at all.
Sep 12 2015
On Saturday 12 September 2015 18:08, Robert wrote:It's unusual, because `float.nan != float.nan`, so one might expect that `typeof(Foo!(float.nan) != Foo!(float.nan))`, whereas this is clearly not the case, even with both the static assert and runtime assert failing. I'm just curious to understand the reasoning behind this, whether it's intentional, and whether it matters at all.I don't know what the compiler actually does, but it looks like the comparison of template value arguments doesn't use equality, but something more akin to `is` instead (bitwise equality). If that's right, then `is(Foo!(float.nan) == Foo!(float.nan))` holds because `float.nan is float.nan` holds. Same behavior with a struct instead of float: ---- struct S { bool opEquals(S other) {return false;} } struct Foo(S s) { } static assert(S.init != S.init); /* not equal */ static assert(S.init is S.init); /* but bit for bit identical */ static assert(is(Foo!(S.init) == Foo!(S.init))); ----
Sep 12 2015
On Saturday, 12 September 2015 at 16:08:31 UTC, Robert wrote:assert and runtime assert failing. I'm just curious to understand the reasoning behind this, whether it's intentional, and whether it matters at all.Types need to mangle to the same name, but using floats in a type name is usually not a good idea. Try pi... How many decimals? A roundoff error and you get a new type.
Sep 12 2015
On Saturday, 12 September 2015 at 15:13:27 UTC, Robert wrote:Hi all, I came across this example, and wondered what your thoughts on it are: <snip> It seems a little unusual to me. RobertFor what it's worth, I was investigating this initially as a discussion about adding type-level values in Rust, and how to handle unusual cases like this. In the process we've managed to break the Idris type system: https://github.com/idris-lang/Idris-dev/issues/2609. There's been quite a lot of interesting discussion about it on the IRC channels for all three languages :) I'd be interested to know how other languages handle this, if anyone knows.
Sep 12 2015
On Saturday, 12 September 2015 at 19:02:16 UTC, Robert wrote:For what it's worth, I was investigating this initially as a discussion about adding type-level values in Rust, and how to handle unusual cases like this.C++ does not allow it. And frankly, having more than a single integer value type as a value parameter in C++ templates is a pointless PITA. I think Go got literal constant values right: make them untyped until bound.
Sep 12 2015
On Saturday, 12 September 2015 at 19:02:16 UTC, Robert wrote:handle unusual cases like this. In the process we've managed to break the Idris type system: https://github.com/idris-lang/Idris-dev/issues/2609.I don't know Idris, but you can't easily unify over floats, because they are samples on an interval, and don't behave like real numbers, but more like underspecified intervals from interval arithmetics. If you want to unify over reals, you probably should do it symbolically. Or just treat float values as literal symbols in the type system. It is useful for configuration: Frequency!342.234 Sometimes it is worthwhile to have an unsound type system. Both D and Dart have somewhat unsound type systems. It puts a burden on the programmer, but can be useful.
Sep 12 2015