问题
It just occurred to me, that F# generics do not seem to accept constant values as "template parameters".
Suppose one wanted to create a type RangedInt
such, that it behaves like an int but is guaranteed to only contain a sub-range of integer values.
A possible approach could be a discriminated union, similar to:
type RangedInt = | Valid of int | Invalid
But this is not working either, as there is no "type specific storage of the range information". And 2 RangedInt instances should be of different type, if the range differs, too.
Being still a bit C++ infested it would look similar to:
template<int low,int high>
class RangedInteger { ... };
Now the question, arising is two fold:
- Did I miss something and constant values for F# generics exist?
- If I did not miss that, what would be the idiomatic way to accomplish such a
RangedInt<int,int>
in F#?
Having found Tomas Petricek's blog about custom numeric types, the equivalent to my question for that blog article would be: What if he did not an IntegerZ5
but an IntegerZn<int>
custom type family?
回答1:
The language feature you're requesting is called Dependent Types, and F# doesn't have that feature.
It's not a particularly common language feature, and even Haskell (which most other Functional programming languages 'look up to') doesn't really have it.
There are languages with Dependent Types out there, but none of them I would consider mainstream. Probably the one I hear about the most is Idris.
回答2:
Did I miss something and constant values for F# generics exist?
While F# has much strong type inference than other .NET languages, at its heart it is built on .NET.
And .NET generics only support a small subset of what is possible with C++ templates. All type arguments to generic types must be types, and there is no defaulting of type arguments either.
If I did not miss that, what would be the idiomatic way to accomplish such a RangedInt in F#?
It would depend on the details. Setting the limits at runtime is one possibility – this would be the usual approach in .NET. Another would be units of measure (this seems less likely to be a fit).
What if he did not an
IntegerZ5
but anIntegerZn<int>
custom type family?
I see two reasons:
- It is an example, and avoiding generics keeps things simpler allowing focus on the point of the example.
- What other underlying type would one use anyway? On contemporary systems smaller types (
byte
,Int16
etc.) are less efficient (unless space at runtime is the overwhelming concern);long
would add size without benefit (it is only going to hold 5 possible values).
来源:https://stackoverflow.com/questions/32602760/no-f-generics-with-constant-template-arguments