No F # generators with constant template arguments?

It just seemed to me that the F # generators did not seem to accept constant values ​​as "template parameters".

Suppose you want to create a RangedInt type such that it behaves like an int, but is guaranteed to contain only a subrange of integer values.

A possible approach would be a discriminatory union similar to:

 type RangedInt = | Valid of int | Invalid 

But this also does not work, since there is no "specific type of storage of information about the range." And 2 instances of RangedInt must be of a different type if the range is also different.

Being a bit more infected with C ++, it will look like:

 template<int low,int high> class RangedInteger { ... }; 

Now the question arises two times:

  • Am I missing something and are there constant values ​​for F # generators?
  • If I hadn't missed this, what would be the idiomatic way to execute such a RangedInt<int,int> in F #?

Finding Tomas Petricek's blog about custom numeric types , the equivalent of my question for this blog article: What if he didn't IntegerZ5 , and IntegerZn<int> custom type family?

+6
source share
2 answers

The language function you request is called dependent types , and F # does not have this function.

This is not a particularly common language feature, and even Haskell (in which most other functional programming languages β€‹β€‹β€œlook”) does not actually have this.

There are languages ​​with dependent types, but I would not consider any of them as the main one. Probably the one that I hear the most is Idris .

+7
source

Am I missing something and are there constant values ​​for F # generators?

While F # has a very strong output type than other .NET languages, it is based on .NET.

And .NET generics only supports a small subset of what is possible with C ++ templates. All type arguments for generic types must be types, and type arguments also fail.

If I hadn't missed this, what would be the idiomatic way to do such a RangedInt in F #?

It will depend on the details. Setting limits at runtime is one option - that would be the usual approach in .NET. Units of measurement would be different (this seems less appropriate).

What if he did not have the IntegerZ5 family, and the IntegerZn<int> non-standard type?

I see two reasons:

  • This is an example, and avoiding generics makes things simpler, allowing you to focus on the point of the example.
  • What other base type will be used anyway? In modern systems, smaller types ( byte , Int16 , etc.) are less efficient (unless space at run time is a problem); long will add size without benefit (it will contain only 5 possible values).
+1
source

All Articles