The rough conclusion that we reached in #117 is that the endpoint types should not necessarily be the same as the eltype.
I decided to implement this in a PR that I will submit shortly, but am filing this issue for conceptual discussion. The key lines that summarize the new implementation are:
struct Interval{L,R,T,TL,TR} <: TypedEndpointsInterval{L,R,T}
left::TL
right::TR
end
There are some important choices I made with my implementation:
- I pushed the endpoint types as far down in the type hierarchy as possible, i.e. only the concrete type
Interval has endpoint types. There are no abstract types with endpoint type parameters. The type of the endpoint can be accessed with e.g. typeof(leftendpoint(i)). This seemed to be the simplest and lowest-risk option, and we can change it later if necessary.
- One choice is what the default eltype should be if the user doesn't specify it explicitly. I originally tried to keep the
eltype as close to the endpoint types except for Integers (e.g. eltype(1..3//2) would be Rational, eltype(1..2) would be Float64), but this ended up feeling too special-case-y. I decided a better option would be to call float to determine the eltype from all endpoint types <:Number in the Interval constructor (i.e. eltype(1..3//2) is Float64). This ended up feeling very nice and consistent and works well with other packages like Unitful.
- I also added a docstring defining the meaning of
eltype for a Domain. It is "the type that best represents elements of the domain according to the criteria chosen by the programmer who created the domain." I think it is best to give users flexibility since it is hard to predict everything Domains will be used for.
What does everyone think?
The rough conclusion that we reached in #117 is that the endpoint types should not necessarily be the same as the eltype.
I decided to implement this in a PR that I will submit shortly, but am filing this issue for conceptual discussion. The key lines that summarize the new implementation are:
There are some important choices I made with my implementation:
Intervalhas endpoint types. There are no abstract types with endpoint type parameters. The type of the endpoint can be accessed with e.g.typeof(leftendpoint(i)). This seemed to be the simplest and lowest-risk option, and we can change it later if necessary.eltypeas close to the endpoint types except forIntegers(e.g.eltype(1..3//2)would beRational,eltype(1..2)would beFloat64), but this ended up feeling too special-case-y. I decided a better option would be to callfloatto determine theeltypefrom all endpoint types<:Numberin theIntervalconstructor (i.e.eltype(1..3//2)isFloat64). This ended up feeling very nice and consistent and works well with other packages like Unitful.eltypefor aDomain. It is "the type that best represents elements of the domain according to the criteria chosen by the programmer who created the domain." I think it is best to give users flexibility since it is hard to predict everythingDomains will be used for.What does everyone think?