Skip to content
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

Why Microsoft.FSharp.Core.netcore is based on netstandard1.5? #1217

Closed
xperiandri opened this issue May 24, 2016 · 23 comments
Closed

Why Microsoft.FSharp.Core.netcore is based on netstandard1.5? #1217

xperiandri opened this issue May 24, 2016 · 23 comments

Comments

@xperiandri
Copy link
Contributor

Is it really necessary to depend on netstandard1.5 and not lower version?
FSharp.Core for F# 4.0 is based on .NET Portable Profile 259 (portable-net45+netcore45+wpa81+wp8) which is netstandard1.0 according to this

I'm just wonder if it is really necessary and Microsoft.FSharp.Core.netcore uses something special from netstandard1.5 API surface not included in netstandard1.0

@xperiandri xperiandri changed the title Why Microsoft.FSharp.Core.netcore is based on netstandard1.5 Why Microsoft.FSharp.Core.netcore is based on netstandard1.5? May 24, 2016
@KevinRansom
Copy link
Member

FSharp.Core.dll for F# 4.0 is based on the BCL that shipped with CLR 4.0.

There are portable variants of FSharp.Core.dll for profile 7 (Windows 8), profile 47 (Win Phone 7), profile 78 (Windows 8 + Phone 8) and profile 259 (Windows 8.1 + Phone 8.1) for developers targeting specific combinations of end platforms.

FSharp.Core.dll for coreclr uses a number of new reflection and ref-emit API's (or at least new to portable) that are not available in 259, it uses the Console class for console IO, and LoadContext. If you look in the project json you will see it's dependencies, for the most they are necessary, I expect we could downward rev a few of the contracts. But in the main the later form of the contracts add back APIs that were missing from portable.

Kevin

@xperiandri
Copy link
Contributor Author

Got it.
So on the stage of RC you will have a look at possibility to lower contract version, right?

@jbtule
Copy link

jbtule commented Jun 28, 2016

So really our options to port to fsharp libraries to work on .net core are:

  • Profile 259 or Profile 78 (which would project a larger api?) ➡️ .Net Standard 1.0
  • Profile 7 ➡️ .NET Standard 1.1
  • dotnet core ➡️ .NET Standard 1.6

@dsyme
Copy link
Contributor

dsyme commented Jul 18, 2016

Closing this discussion for now (feel free to add more to it)

@dsyme dsyme closed this as completed Jul 18, 2016
@21c-HK
Copy link

21c-HK commented Dec 6, 2016

@KevinRansom Any updates? If not, does FSharp.Core really need to use the Console class?

@KevinRansom
Copy link
Member

@21c-HK --- printfn --- perhaps.

@xperiandri
Copy link
Contributor Author

Maybe it is reasonable to split FSharp.Core into a few packages?

I have F# bindings for System.Collections.Immutable and I would perfectly throw away F# collections.
There is a task computation expression in an Orleankka (because of custom task scheduler) that will be much better for interoperability so asynchronous workflows can be thrown away too.

Hence what is the reason to have a single monolithic package instead of small compostable pieces?

@21c-HK
Copy link

21c-HK commented Dec 6, 2016

--- printfn --- perhaps.

Great example! That really makes it difficult to go down to .NET standard 1.0. In hindsight, it is really unfortunate that this function is preventing F# from being universally portable.

@cartermp
Copy link
Contributor

cartermp commented Dec 6, 2016

FYI the code for that is here: https://github.com/Microsoft/visualfsharp/blob/master/src/fsharp/FSharp.Core/printf.fs#L1381

And the baseline is netstandard1.3: https://apisof.net/catalog/System.Console.Out

We're in a bit of an annoying point-in-time issue with this right now, given that .NET Standard 2.0 is on the horizon and is the "true" .NET Standard Library that .NET things will depend on in the future, in addition to bringing back all the critical APIs which are unavailable on .NET Core and .NET Standard today.

The way I see it, there are a few options here:

  1. Split FSharp.Core into a few packages, and have FSharp.Core itself just be a metapackage which targets the highest version of all the targets of the individual packages it's made up of (likely netstandard16 or netstandard13)
  2. Try to lower the version of FSharp.Core to netstandard13 and keep it as-is
  3. Do nothing and wait for .NET Standard 2.0, maintaining older versions of FSharp.Core until it's safe to obsolete them (e.g., .NET Framework 4.5.1 and below is now unsupported by the .NET team, so we could cut support for those immediately, honestly)

Regardless, I think it's a bit of a lower priority thing at the moment because we're still not at RTM tooling support for .NET Core and .NET Standard (even for C#).

@21c-HK
Copy link

21c-HK commented Dec 6, 2016

The suggestion by @xperiandri is brilliant. Maybe consider making FSharp.Core more modular the way .NET Core makes the .NET Framework more modular. That way we might be able to get a base assembly of FSharp.Core that is compatible with .NET Standard 1.0 and additional assemblies that add functions like printfn if needed.

I guess this shoule be a separate suggestion though.

I always believed that assemblies should be defined by their dependencies and not by other arbitrary factors.

@21c-HK
Copy link

21c-HK commented Dec 6, 2016

Sorry, @cartermp beat me to it with option 1, which I think is the best option out of the three, but I have no insight in what the current status and priorities of .NET Core and F# are. I like option 1 because it is the cleanest. Option 2 & 3 always bite you in the ass in the long-run.

@KevinRansom
Copy link
Member

Not at all 21c-HK use the Portable 259 version of FSharp.Core.dll and only use the Api's it allows. Then you can create very portable libraries that will run on platforms from Xamarin iOS And Android all the way to Windows Desktop, Windows Metro and Win Phone 8.

.Net Standard of it's various versions will also achieve a good range of portability. But right now we do have a point in time problem, I think .NetStandard 2.0 will really rock the cross platform thing.

The biggest issue with refactoring FSharp.Core.dll is compatability with legacy code and libraries. If we were starting now we might factor it differently ... although not necessarily ... and it's fair to say that every developer values slightly different things.

Allthough we could use type forwarders to move types about ... but then deployment gets really messy, however, nuget and paket may offer ways out of that.

Kevin

@21c-HK
Copy link

21c-HK commented Dec 6, 2016

I was hoping that we could get rid of portable profiles and use a shared core instead. Ideally, there would be a FSharp.Core that everyone uses and the just add to it. That way, we could prevent problems like the inlining bug in F# 3.1 that was exclusive to profile 259. I think that all these different editions of the FSharp.Core make it harder to maintain and discover these kind of bugs.

@KevinRansom
Copy link
Member

@21c-HK
It seems to me to be likely that profiles are here to stay ... hopefully they will become less necessary though. And I am expecting that NetStandard 2.0 will provide the core for a cross platform API.

@xperiandri
Copy link
Contributor Author

Created separate issue about splitting #1955

@21c-HK
Copy link

21c-HK commented Dec 10, 2016

Edit: Updated to correct the out-dated information in Introducing .NET Standard thanks to @cartermp (i.e. .new APIs in NET Standard 1.5 and 1.6 will not be removed and .NET Standard 2.0 stays a strict superset of earlier versions).

@cartermp I think you should really go for .NET Standard 1.4 or 1.3 because UWP 10 (and all other .NET platforms that are relevant for the future) target 1.4.

@KevinRansom

FSharp.Core.dll for coreclr uses a number of new reflection and ref-emit API's (or at least new to portable) that are not available in 259

The .NET team deems Reflection Emit as an optional self-contained component with regards to the .NET standard that should be provided as a seperate NuGet package on top of some .NET standard. I don't know how feasible that is for F#, but the corresponding quotes from Introducing .NET Standard are as follows:

Can I still use platform-specific APIs?

[...]
Registry. The Windows registry is a self-contained component that will be provided as a separate NuGet package (e.g. Microsoft.Win32.Registry). [...]
[...]
Reflection Emit. Reflection emit is reasonably self-contained and thus we plan on following the model as Registry, above. There are other APIs that logically depend on being able to emit code, such as the expression tree’s Compile method or the ability to compile regexes. In some cases we’ll emulate their behavior (e.g. interpreting expression trees instead of compiling them) while in other cases we’ll throw (e.g. when compiling regexes).

Reading that blog post and re-reading all the comments in this thread, I think that @cartermp's 2. option to try to lower the target to .NET Standard 1.3 would give Microsoft.FSharp.Core.netcore portability to all relevant future platforms without an unreasonable amount of effort or breaking changes (I guess, but you guys would know better than me).

Then in the future, instead of targeting .NET Standard 2.0 with a single package, we could add the .NET Standard 2.0-specific APIs as a modular package on top of the monolithic Microsoft.FSharp.Core.netcore package targeting .NET Standard 1.3.

@cartermp
Copy link
Contributor

@21c-HKnetstandard1.x is here to stay, and represents the first "family" of .NET Standard Library targets. It's also, based on community feedback, compatible with .NET Standard 2.0 and with no breaking changes. .NET Standard Library 2.0 is planned to be a strict superset of .NET Standard 1.6.

While this doesn't mean that .NET Standard 1.6 as the target for FSharp.Core is where we want to be, it means we don't need to prioritize a change at this time.

Ultimately this is the engineering team's decision, but I personally think that netstandard1.3 is the right target for FSharp.Core, as this gets us compatibility with UWP and .NET Framework 4.6+. We'll also be compatible with Type Providers (which will target .NET Standard 2.0), because they can depend on us due to the forward-compatibly nature of .NET Standard targets. However, this does leave us unable to incorporate any Type Providers into FSharp.Core in the future, unless we were to bump the version of FSharp.Core up to .NET Standard 2.0.

@21c-HK
Copy link

21c-HK commented Dec 11, 2016

Thank you for the correction and pointing me to the FAQ on the .NET Standard! I missed that somehow.

However, this does leave us unable to incorporate any Type Providers into FSharp.Core in the future, unless we were to bump the version of FSharp.Core up to .NET Standard 2.0.

Could you please clarify why type providers would need to be in FSharp.Core? Does referencing another package instead (e.g. FSharp.Core.TypeProviders) that targets .NET Standard 2.0 preclude certain use cases of type providers?

@cartermp
Copy link
Contributor

It was a hypothetical thing. If, for some reason, we decided to add a set of Type Providers to FSharp.Core, the target of FSharp.Core would have to get bumped up to .NET Standard 2.0.

I should have clarified the general case: If we wanted to have some kind of functionality in FSharp.Core which depended on .NET APIs which are only available in .NET Standard 2.0, we need to bump the target for FSharp.Core.

@21c-HK
Copy link

21c-HK commented Dec 11, 2016

Is the F# team against or for "layering" new F# features that require .NET Standard 2.0 on top of a Microsoft.FSharp.Core.netcore that targets .NET Standard 1.3/1.6 via separate packages?

In other words, will "layering" be the preferred option to introduce new features into Microsoft.FSharp.Core.netcore or would you prefer to "retarget" the entire package to .NET Standard 2.0?

I understand that if there was a non-optional F# feature that needed .NET Standard 2.0, then Microsoft.FSharp.Core.netcore should just be retargeted to .NET Standard 2.0.

@cartermp
Copy link
Contributor

cartermp commented Dec 11, 2016

Personally I'm not opposed to such a layering, no. I doubt anyone here is; however, .NET Standard 2.0 presents a completely different world that I don't think we're really in a good position to make a call one way or another right now.

@21c-HK
Copy link

21c-HK commented Dec 11, 2016

FYI, the most relevant .NET Standard versions at the current point in time seem to be as follows:

  • .NET Standard 1.4 for Universal Windows Platform and .NET Framework 4.6 (since the latter is already part of .NET Standard 1.3)
  • .NET Standard 1.6 for .NET Core 1.0, Mono 4.6, Xamarin.iOS 10.0, Xamarin.Android 7.0 (i.e. recent versions of these platforms)
  • .NET Standard 2.0 for .NET Framework 4.6.1 and future versions of .NET Core, Mono, Xamarin.iOS, Xamarin.Android and Universal Windows Platform

I am really excited about .NET Standard as you might noticed ;-).

@21c-HK
Copy link

21c-HK commented Dec 12, 2016

.NET Standard 2.0 presents a completely different world that I don't think we're really in a good position to make a call one way or another right now.

FYI, according to the .NET Core roadmap, .NET Core 1.2 will be released in Spring 2017 targeting NET Standard 2.0, which .NET Framework 4.6.1 also targets (except for not supporting 43 new APIs that the .NET Standard 2.0 adds).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants