Design notes
See original GitHub issueAfter using F#+ and designing types implementing the required static member we observe that types end up with undesired duplication of signature, for example:
ZipList.map f x
(function) and ZipList.Map(x, f)
(static member).
This can be solved by “hiding” the static member by marking it as “deprecated”, but I was thinking that if we use the applicative operator for map
we solve that issue and on top of that this code:
(+) <!> ZipList [1;2] <*> ZipList [3;4]
Will just work, independently of F#+ generic calls. I mean even if FSharpPlus namespace is not open and generic operators are not in scope, the above code will compile, without resolving any complicated static constraint.
So, I propose the following design guideline:
-
For unary operations, like
ToSeq
,OfBytes
we use lower case. The exception here isReturn
which is a keyword in lowercase. -
For binary:
- Is there any standard/wide accepted operator (
<!>
,<|>
,>>=
,=>>
,<*>
…) ?=>
Use it. - Does it make sense tupled
=>
Use it tupled, lowercase. - Define it Uppercase but in the client code is recommended to use an attribute to hide it.
- Is there any standard/wide accepted operator (
-
For ternary operations or more: 2) and 3) above applies.
All this leads one more time to the question about the utility of the Extensions attributes. I addition, now we’ve seen many operators need internal tupling of arguments in order to avoid upcasting to interfaces at overload resolution, which render those attributes unusable.
For C# usability we may consider instead the extensions defined in Extensions.fs file.
We will still have duplicated members/functions internally, but this is fine because it allows us to expose the non-generic function and simplifies the implementation of the static member, which is desirable, I mean to keep the body of the static member short (a call to the non generic).
Issue Analytics
- State:
- Created 6 years ago
- Comments:13 (13 by maintainers)
Top GitHub Comments
Another way of hiding methods could be with one of these attributes:
Anyway, that’s a small detail. Worst case we leave them visible, but the key change here will be having to define:
static member (>>=)
instead ofBind
static member (<!>)
instead ofMap
static member (<|>)
instead ofAppend
Another C# aspect to consider is the other way around, using C# from F#, in this case would mean using a type defined in C#. That’s something I had in mind when I came up with this design, but for
bind
andmap
we expect an F# function, not aFunc
.