-
Notifications
You must be signed in to change notification settings - Fork 98
Rewrite C# Compatibility Layer as bindings in C# #285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
For the generic type parameters portion of this work, I think one thing that can help is to explicitly name each generic type parameter with the parameter it applies to. This requires a bit of work but the name could guide the user to what the variable should be. Alternatively, instead of a flexible type |
I am not sure if i understand this correctly. In the case of actual usage of generics in F# code, this is what it would look like, right? type Foo() =
static member Bar (paramOne: 'T, paramTwo: 'U) = <something>
//instead name the type of the parameters
type Foo() =
static member Bar (paramOne: 'ParamOne) (paramTwo: 'ParamTwo) = <something> Intellisense in C# is more helpfull because i can see what type belongs where.
But how would i do this when my actual signature looks like this? type Foo() =
static member Bar (paramOne: #IConvertible , paramTwo: #seq<#IConvertible>) = <something> I cannot name the type, as it is more then an actual generic type there, but the flexible type still gets icky in the C# intellisense.
|
What I ended up doing when I was tinkering here actually ended up introducing more generic parameters, so I'm not sure if my suggestion will be useful in the end: open System
type Foo =
/// <summary>Makes a grid widget with a given set of lengths and widths for the cells</summary>
/// <param name="lengths">the lengths of the cell blocks</param>
/// <param name="widths">the widths of the cell blocks</param>
/// <typeparam name="'length">a value representing the length of a cell</typeparam>
/// <typeparam name="'lengthSeq">a sequence of cell lengths</typeparam>
/// <typeparam name="'width">a value representing the width of a cell</typeparam>
/// <typeparam name="'widthSeq">a sequence of cell widths</typeparam>
/// <returns></returns>
static member Bar<'length, 'lengthSeq, 'width, 'widthSeq
when 'length :> IConvertible
and 'lengthSeq :> seq<'length>
and 'width :> IConvertible
and 'widthSeq :> seq<'width>
>(lengths: 'lengthSeq , widths: 'widthSeq)= ()
Foo.Bar([1;2;], [2.0;3.0]) this is a very contrived example, though... |
Ah gotcha, thanks! It looks certainly like it would make the the API more C#-friendly, but if this results in 2 annotations per What about usage in F#? the intellisense would look different and include the generic annotation right (so |
Amazing to see this is already in the works @kMutagene! We're currently working on some sample ML notebooks for C# and we want Plotly.NET to be our default plotting library. Let us know how we can help 🙂 https://github.com/dotnet/csharp-notebooks/tree/main/machine-learning |
@luisquintanilla I think i have finished prototyping and will update the original issue with guidelines on the API conversion. How you can help depends on the time you want to invest 😆 Once the guidelines are up, this a a straightforward copy-paste-adapt thing, where each high level Chart API gets C# bindings in the described style. So if you want to contribute to the codebase directly that would be awesome. However if that's not on the menu, i think giving me/us an idea on the APIs you need for the notebooks (what type of charts are you creating? are you using custom styles or are defaults enough? etc.) would also help, as we could then prioritize bindings for those APIs. |
I updated the original issue with the results of my prototyping so far. Feedback is very welcome! |
Great! We'll take a look and provide feedback :) |
These are the graphs we're currently using: https://github.com/dotnet/csharp-notebooks/blob/main/machine-learning/REF-Graphs%20and%20Visualizations.ipynb. Having intelli-sense and signature help work for those graphs would be a great start and unblock most of our scenarios at the moment :)
Eventually I'd love to get parity but I think just Bar chart is missing from #294 for our main use cases.
Default styling is fine as long as it's readable in VS's Light Theme and Dark Theme :) |
It's on the menu! Let us know how we can jump in. |
Sure, parity is the goal in the end, but as you can see in #294, the scope of Chart API contains >90 charts (ignoring overloads in the main lib btw, so if we want to support tupled xy data instead of one array for x and y each that number easily doubles) and that is ignoring any styling functions and object abstractions. So i would say the main goal for now is getting the C# API to a usable level in your example notebooks, which seems to be almost the case already.
Very cool! Once #294 with the decreased scope is merged, you can target PRs with implementations of any C# binding to the |
@JakeRadMSFT @luisquintanilla |
closing this as there is a native C# bindings package now |
Plotly.NET CSharp layer
Update 30/05/22: C# high-level Chart API layer design notes
The C# API layer for Plotly.NET aims to remove the friction created by language specific issues when using the F# API from C#.
It uses the following methods to reach that goal:
Microsoft.FSharp.Core.FSharpOption<T>
signatures for optional parameters and significantly reduces visual noise in intellisenseIt is currently only aimed at wrapping the high-level Chart creation and styling APIs.
The
Chart creation APIs
(e.g.Chart.Scatter
,Chart.Histogram
) get equivalents as static methods of thePlotly.NET.CSharp.Chart
class.The
Chart styling APIs
, which were previouslyGenericChart
extension methods on the F# layer will be re-implemented as C# extension methods. Fluent interface style APIs are best at home in the C# API and i think once it is 100% ported we might remove it from the F# API alltogether to reduce duplicate code.The C# API layer functions should always call the respective F# functions and match the parameter count and names 1:1. XML docs should also be the same. Optional parameters on the C# side are used with
null
as default values and are subsequently wrapped asFSharpOption
s ( null -> None, rest -> Some rest) for calling the F# methods. There are helper functions implemented for this.The work for this is done on the
csharp-layer
branchHere is an example of a full binding for the
Chart.Point
method (see also here):Example usage:
Intellisense(without annotating the generics):
Thanks @WhiteBlackGoose for helping me with this.
Original issue description
This is the issue where progress/decisions about the new C# layer
Plotly.NET.CSharp
will be tracked.While big efforts have gone into being as C# friendly as possible in the F# source code (by for example providing static type extensions for a fluent interface style API), some things are still not very usable from C#:
Optional parameter bloat
optional parameters in F# methods are displayed to have type
FSharpOption
in intellisense (minor issue without impact on compatibility, but makes method signatures quite unreadable)Explicit type annotation bloat
#IConvertible
in F# signatures makes explicit type annotations necessary when calling from C#. The more usage of#IConvertible
, the less usable the method gets, as there have to be type annotations for optional parameter that are not used. Here is an example that is very bad:FSharpFunc
as return value from F# APIThere are Styling APIs that return functions - a completely normal F# thing to do. Those have to be used in C# by using the
Invoke
method (see #187 for an example where this caused confusion) and are overall not very csharpy.But there are also some good news. This does not have to be a complete C# rewrite of the library. Things we most likely do not have to touch:
StyleParam
module is quite usable from C# - here, the added methods for compatibility seem to be sufficientAdditionally, i think we might only provide bindings for the high level API. Whether to add low level bindings as well depends on community needs and amount of people helping to write these bindings.
Guidelines for contributors
I will post guidelines on how to help here once we decided on the way on how to implement this.
The text was updated successfully, but these errors were encountered: