We currently use operator overloading for DateTimes. We can perform the following three operations:
DateTime - DateTime = Time
DateTime + Time = DateTime
DateTime - Time = DateTime
Every other addition/subtraction operation with DateTimes is disallowed. This is important because constructions like DateTime + DateTime are not meaningful.
The currently implemented operator overloading works fine whenever we have concrete types:
>>> now() + 4 days
= Sat, 15 Jun 2024 18:44:56 +0200 [DateTime]
but if fails if intermediate type variables are involved (see similar issue for structs here: #459). For example, we currently can not do this:
fn id(x) = x
id(now()) + 4 days
Similarly, if we write the function
fn add_four_days(dt) = dt + 4 days
without a type annotation for the parameter type, we will not get the most general type inferred (which cannot even be expressed in Numbats type system at the moment).
Ideally, we would have something like a (multiparameter) type class or trait (Add, Sub), that we could use to model operator overloading. This would allow us to infer the most-general type (using a Rust-like syntax again):
fn add_four_days<A, B>(dt: A) -> B
where A: Add<Time, Output = B>
= …
which would allow us to use this function both with DateTime and Time.
If it were only for DateTime, I think we might be able to live with the current restriction. But there might be some other cool examples where we could make use of proper Add/Sub constraint handling. For example, we could introduce specialized types for Celsius and Fahrenheit that would potentially implement (in close analogy to what we have for DateTime and Time):
Celsius - Celsius = Kelvin
Celsius + Kelvin = Celsius
Celsius - Kelvin = Celsius (we could think about disallowing this as well…)
but disallow things like Celsius + Celsius because they make no sense.
Ref: #184
Another use case might be logarithmic units like decibel, for which we could implement specialized addition/subtraction operations.
Ref: #387
We could start by only allowing those constraints to be resolved internally by the type checker, without going all in on user-definable type classes. But those would be interesting as well, obviously:
We currently use operator overloading for
DateTime
s. We can perform the following three operations:DateTime
-DateTime
=Time
DateTime
+Time
=DateTime
DateTime
-Time
=DateTime
Every other addition/subtraction operation with
DateTime
s is disallowed. This is important because constructions likeDateTime
+DateTime
are not meaningful.The currently implemented operator overloading works fine whenever we have concrete types:
but if fails if intermediate type variables are involved (see similar issue for structs here: #459). For example, we currently can not do this:
Similarly, if we write the function
without a type annotation for the parameter type, we will not get the most general type inferred (which cannot even be expressed in Numbats type system at the moment).
Ideally, we would have something like a (multiparameter) type class or trait (
Add
,Sub
), that we could use to model operator overloading. This would allow us to infer the most-general type (using a Rust-like syntax again):which would allow us to use this function both with
DateTime
andTime
.If it were only for
DateTime
, I think we might be able to live with the current restriction. But there might be some other cool examples where we could make use of properAdd
/Sub
constraint handling. For example, we could introduce specialized types forCelsius
andFahrenheit
that would potentially implement (in close analogy to what we have forDateTime
andTime
):Celsius
-Celsius
=Kelvin
Celsius
+Kelvin
=Celsius
Celsius
-Kelvin
=Celsius
(we could think about disallowing this as well…) but disallow things likeCelsius
+Celsius
because they make no sense.Ref: #184
Another use case might be logarithmic units like decibel, for which we could implement specialized addition/subtraction operations.
Ref: #387
We could start by only allowing those constraints to be resolved internally by the type checker, without going all in on user-definable type classes. But those would be interesting as well, obviously: