using Visual Studio 2017 I'm trying to compile the following F# snippet
type Foo() =
inherit System.Tuple<string,string>("","")
which fails telling me that I cannot inherit from sealed type. I inspected FSharp.Core and it's not sealed. I'm also convinced that this compiled with VS 2010.
Any ideas? Is this caused by extra F# metadata? I know that F# treats tuples in special way
As of F# 4.1, F# treats all System.Tuple instances as an F# tuple, which cannot be inherited from.
Related
I created an F# 'Nunit' project using a template in VS 2019 to do some testing, and the default fixture code it created was the following:
namespace Tests
open NUnit.Framework
[<TestClass>]
type TestClass () =
[<SetUp>]
member this.Setup () =
()
[<Test>]
member this.Test1 () =
Assert.Pass()
It's an otherwise ordinary looking class, except the curiosity on the class declaration. I expected to see [<TestFixture>], but instead I see [<TestClass>], the same name as the auto-generated type. I suspect that this is a bug in the project template, but strangely, F# will happily compile this, with a note that it probably won't be compatible with other .Net languages:
warning FS3242: This type does not inherit Attribute, it will not work correctly with other .NET languages.
crystal clear for me. My question is, why does F# even allow this? Do the reflection capabilities in .Net even work for such an attribute in F#? What would a potential use-case be?
Historically the check was forgotten to be added to the compiler. When it was discovered, I propose to make it compilation error, but it ended up as a warning for backward compatible reasons. See https://github.com/Microsoft/visualfsharp/pull/5192 and https://github.com/Microsoft/visualfsharp/pull/5610 for details.
Alas, I do not have the answer to the question why F# allows this. A quick experimentation shows that using ordinary classes as attributes works - at least in a very basic situation:
type A(n:int) =
member x.N = n
[<A(10)>]
type B() = class end
(typeof<B>.GetCustomAttributes(true).[1] :?> A).N
The Microsoft.CodeAnalysis.LanguageNames class has an entry for F#:
public static class LanguageNames
{
public const string CSharp = "C#";
public const string VisualBasic = "Visual Basic";
public const string FSharp = "F#";
}
This got me excited, I thought I could let my users also use F# just by toggling one property. Alas, it doesn't seem to be the case. There are Roslyn nuget packages for C# and VB.NET but nothing for F#.
Is support for analyzing and running F# code planned in Roslyn?
If not, what alternatives would you recommend for parsing and executing F#?
You can use F# Compiler Service.
The problem with F# on Roslyn is that F# has been self-hosted from the very start, while C# and VB compilers were written in C++ for a long time. By the time C# and VB finally grew up and got Roslyn, F# already had a well developed compiler with its own architecture. Worse, that architecture could not be easily followed in Roslyn (though I think they didn't even try), because it makes heavy use of language features not available in C# and VB.
I wonder what's going on here...
I just created a new, empty F# Console application in Visual Studio 2013 (using F# 3.1 and .NET 4, FSharp.Core Version 4.3.1.0) and added the Reactive Extensions Main Library using Nuget: Install-Package Rx-Main
Now check this out:
This works and the hovering over test shows val test: unit -> System.Reactive.Subjects.Subject<'a>. As expected. Then I added the new keyword.
Interesting. Does anybody know why adding the new keyword breaks the code? For reference, if you additionally specify the type parameter, it works:
I can't find a spec reference off-hand, but when using new explicit type args are required. You need to do:
let test() = new System.Reactive.Subjects.Subject<_>()
It appears to be a static class, and static classes cannot be newed up.
http://msdn.microsoft.com/en-us/library/system.reactive.subjects.subject%28v=vs.103%29.aspx
And to elaborate on your specific error message, it means there is public no constructor available that accepts 0 parameters. As far as I know, static classes only have private, parameterless constructors.
If I use the F# Type Providers from the assembly FSharp.Data.TypeProviders 4.3.0.0, I am able to create types in a very simple F# library. I am then able to use those types without any dependency on the assembly FSharp.Data.TypeProviders. That is pretty sweet! Here is an example:
I created an F# library project called TryTypeProviders. I put this in the .fs:
module TryTypeProviders
type Northwind = Microsoft.FSharp.Data.TypeProviders.ODataService
I then am able to use the F# library from a C# project:
public static void Main()
{
var c = new TryTypeProviders.Northwind();
foreach (var cust in c.Customers)
Console.WriteLine("Customer is: " + cust.ContactName);
Console.ReadKey(true);
}
I haven't been able to find any working examples of how to create a type provider like this. The type providers in FSharpx.TypeProviders are not accessible from C#. My guess is that they are erased types and not generated types. I'm still a little fuzzy on which is which, but it is defined here as:
Generated types are real .NET types that get embedded into the assembly that uses the type provider (this is what the type providers that wrap code generation tools like sqlmetal use)
Erased types are simulated types which are represented by some other type when the code is compiled.
The samples from the F# 3.0 Sample Pack mentioned in the MSDN tutorial are not working for me. They build, but when I try to use them I get errors.
open Samples.FSharp.RegexTypeProvidertype PhoneNumberRegEx = CheckedRegexProvider< #"(?<AreaCode>^\d{3})-(?<PhoneNumber>\d{3}-\d{4}$)">
open Samples.FSharp.MiniCsvProvidertype csv = MiniCsvProvider<"a.csv">
It was last released in March of 2011 and my guess is that they don't yet reflect the final version of type providers that shipped with Visual Studio 2012.
F# Type Providers look like a great technology, but we need help building them. Any help is appreciated.
The reason why standard type providers (for OData, LINQ to SQL and WSDL) work with C# is that they generate real .NET types behind the cover. This is called generative type provider. In fact, they simply call the code generation tool that would be called if you were using these technologies from C# in a standard way. So, these type providers are just wrappers over some standard .NET tools.
Most of the providers that are newly written are written as erasing type providers. This means that they only generate "fake" types that tell the F# compiler what members can be called (etc.) but when the compiler compiles them, the "fake" types are replaced with some other code. This is the reason why you cannot see any types when you're using the library from C# - none of the types actually exist in the compiled code.
Unless you're wrapping existing code-generator, it is easier to write erased type provider and so most of the examples are written in this way. Erasing type providers have other beneftis - i.e. they can generate huge number of "fake" types without generating excessively big assemblies.
Anyway, there is a brief note "Providing Generated Types" in the MSDN tutorial, which has some hints on writing generative providers. However, I'd expect most of the new F# type providers to be written as erasing. It notes that you must have a real .NET assembly (with the generated types) and getting that is not simplified by the F# helpers for building type providers - so you'll need to emit the IL for the assembly or generate C#/F# code and compile that (i.e. using CodeDOM or Roslyn).
If one uses the F# Interactive Shell (FSI), the inferred expression type (signature) is printed to the console along with its value:
val it : int * string * float = (42, "Hello F#", 42.0)
How can I mimick the same behaviour in my own code, e.g. to get the inferred types as string for a F# expression?
I don't need to dynamically evaluate any F# expressions, the expressions are known in compile time and are part of my (static) F# code. I need this feature to be able to mimick the FSI output in LINQPad for my F# demos.
Using Unquote
Unquote has a facility for getting the F# signature of a type. Simply download the latest release and add a reference through LINQPad to Unquote.dll, then you can do e.g.
If you're interested, you can peak at the source code for the implementation of the FSharpName Type extension: https://github.com/SwensenSoftware/unquote/blob/2.1.0/Unquote/ExtraReflection.fs#L54
Using FsEye
Another neat approach would be to use LINQPad's beta Custom Visualizer API to embed FsEye into LINQPad (FsEye uses the same F# type signature printing algorithm as Unquote). This is also very simple, all you need to do is download LINQPad beta, download and reference FsEye.dll from the latest release of FsEye, then you can do e.g.
If you look at the F# compiler code and see how the --sig option is handled by the compiler I think that will get you what you're looking for. More about the --sig option and signatures here:
Signatures (F#)