Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
signature improvement for generics #674
Signature Improvement for generics
the generic portion of a method or function gets ignored when fsi produces the signature description. In the case below, we've got nothing to show for x prime "<'x>". Can we improve the situation?
Issue -- there are two entries for B in the below. Only when a type is a standard argument, does the signature come close to what I was expecting. Shouldn't the generic version produce a different signature?
The existing way of approaching this problem in F# is to make a mental note of what is actually going on underneath.
Pros and Cons
The advantages of making this adjustment to F# are -> Some("type signatures are also accurate + explicit for generic cases")
The disadvantages of making this adjustment to F# are -> None.
Estimated cost (XS, S, M, L, XL, XXL): XS
Related suggestions: n/a
Affidavit (please submit!)
Please tick this by placing a cross in the box:
Please tick all that apply:
I'm not sure I understand the issue. The second method
Just trying to understand what you're suggesting ;)
Yes, it's clearer now. I think the main issue with your code is that you are using generics that doesn't appear anywhere in the signature, hence you don't see it back in the signature F# gives you. I.e. suppose you have:
static member B<'x>(n, a:'x) = typeof<'x>.Name,[for i = 0 to n-1 do yield i]
This would give you the signature like it's expected (note the appearance of
I don't think changing the inferred signature to something else than it actually is is the right way forward, but perhaps inference could detect that it is a generic signature where the generic type parameter is a requirement (as opposed to being implicit, which is usual in F#, as in my example above).
For instance, instead of
That way it wouldn't change the actual signature and the shown signature is still legal syntax and actually maps the original definition. An added benefit would be that in the output of your type it becomes immediately obvious what the difference are:
type Abc = class new : unit -> Abc static member A : unit -> string * int list static member B : n:int -> string * int list static member B<'a> : n:int -> string * int list // now this is distinguishable static member B : ty:Type * n:int -> string * int list end
Whether this is easy or hard to achieve, I don't know. Type inference is a tricky thing in the compiler.
interesting... it's as you said... thanks for mentioning the not used + inference idea...
... signature is...
I'm not sure if this is predictable enough though... going back a step to the weird behaviour:
and yet, inference or not, 'x has influenced behaviour.
It might not affect most people in practice, yet, maybe it's a rough enough edge to be worthy of sanding one day. The context is "reasoning with types + signatures" + type providers + it came up in actual work that I'll be using for teaching purposes. I'll skip over this so that I don't confuse anyone. I'll definitely avoid the generic notation, which would have been more compact, yet probably not have added much in terms of readability. I do like the way <'x> works generally -- just need to avoid it in this context. Perhaps, hand cranking the type signature is acceptable. Thanks.
Most of the time you won't need it, F#'s auto-generics take care of that.
It influenced behavior, yes, but
Though I do see your point: if the generic parameter is specified, it is probably for a good reason (i.e., in your case you use it with
there are implications beyond F# only scenarios, like perhaps at that point, you are injecting IL into a byte array, or translating to something further afield. The finer point is, the programmer was explicit, so we should not override this.
Also, it's inconsistent with a simpler case:
The language needs to be predictable so that you can read the code, and not be forced to run it to understand what is going on.
NB. we still don't know if this is just pretty printing.
What I'm reading from this suggestion is to pretty-print generic type arguments for functions and members. For example, in FSI:
Class and constructor show generic type argument:
Member does not:
Neither does a function:
I think that's reasonable and probably doesn't require a language change. Assuming it does not, then this seems like a fine feature request in the Visual F# repository.
@cartermp: I've been trying to catch glitches and say something about them without overthinking it. I was unsure of scope at the beginning of this.
@realvictorprm: re: style -- probably the way a let does it currently is the right way to go. Although I'd prefer to have fewer angle brackets, this is the idiomatic way in F# / .Net.