Rounding out Visual F# 4.0 in VS 2015 RC

Today marks the release of Visual Studio 2015 RC, which includes the latest updates to the Visual F# 4.0 language and tools.  Download the RC here, and review the VS release notes here.

Back in November, we described the F# 4.0 features that were completed in time for the Visual Studio 2015 Preview build. New features like constructors as first-class functions, simplified mutable/ref values, a normalized collections API, and more were warmly received.  We didn’t stop there, though!

This post describes the F# 4.0 work that’s been completed since Preview.  Together with the features announced earlier, this completes the planned feature set for F# 4.0. Bug fixes and performance optimizations will continue to be accepted up until VS 2015 RTM. The F# bits that ship with today’s RC build map to commit 76ae08d.

Built by the F# community

Visual F# 4.0 was built completely in the open by F# community developers, in partnership with the Visual F# team at Microsoft.  It represents the work of 38 contributors, over 75% of whom have no Microsoft affiliation.

We extend a big thank you to all of the community devs who help us make F# and the Visual F# Tools great!

 Feedback

As you try out VS 2015 RC, please log any F#-specific issues directly on GitHub.  Feedback on Visual Studio itself can be sent through Connect, UserVoice, or as quick notes through Send-a-Smile directly in the IDE.

Here’s what’s been added since the Preview build:

Language

Implicit quotation of method arguments

Method arguments of type FSharp.Quotations.Expr<_> can now be marked with the [<ReflectedDefinition>] attribute, enabling automatic quotation of the corresponding argument expressions at callsites. This enables seamless syntax for various meta-programming scenarios that depend on access to the underlying AST, e.g. LINQ-style transformations or R-style plotting routines that label chart axes automatically.

A simple example of using this feature in an expression printing method:

autoquote

Extended preprocessor grammar

F# preprocessor directives now support the standard logical operators &&, ||, and !, as well as grouping via (  ).  This leads to significantly cleaner conditionally-compiled code, and the ability to easily express conditions that previously required code duplication.

preproc

Rational exponents in units of measure

F# units of measure were previously limited to support only integer exponents. With F# 4.0, units can now be raised to arbitrary rational powers. Certain physical sciences, such as electrical engineering, frequently use such fractional powers for units.

rationalUOM

Inheritance from types with multiple generic interface instantiations

Earlier versions of F# disallowed types from implementing the same .NET interface at multiple generic instantiations, or even inheriting from C# types that did so.  This was due to complexities in how multiple generic instantiations would interact with F# type inference.

Although the former restriction still applies, the restriction on inheritance has been lifted in F# 4.0.  This significantly simplifies interoperability with certain C#-based APIs, an increasing number of which rely on such designs.

It is also now possible to work around the remaining restriction by defining a small type hierarchy in pure F# code, each member of which implements an additional generic instantiation:

interface

Non-nullable provided types

Provided types which report the attribute [<AllowNullLiteral( false )>], will now be treated as non-nullable in the same way as standard F# types.  The brings stronger safety guarantees to provided types and aligns them more closely with patterns and idioms from the rest of the language.

Multiple properties in [<StructuredFormatDisplay>]

F# types specifying custom %A string formatting via the [<StructuredFormatDisplay>] attribute were previously limited to interpolating just a single property value.  StructuredFormatDisplay now supports an arbitrary number of interpolated properties, as well as escaped { } brackets.

structuredformat

Extension properties in object initializers

F# supports not just extension methods, but extension properties, as well.  Settable extension properties can now be assigned directly within F# object initializers, allowing for one-step initialization of data.

extensionset

Leading ‘Microsoft’ prefix optional

Although Microsoft publishes the Visual F# Tools for use in Visual Studio on Windows, the F# language itself is supported cross-platform by a variety of companies, and its primary advocate is the independent, community-governed F# Software Foundation.

In this vein, to keep F# code itself vendor- and platform-neutral, the leading “Microsoft.” can now be optionally omitted when referring to namespaces, modules, and types from the FSharp.Core runtime.

msftprefix

Runtime

Optimized non-structural comparison operators

By default, the =, <>, <, >, <=, >=, compare, min, and max operators in F# represent structural equality and comparison.  This is a sensible choice for a data-oriented functional language, but presents problems in some scenarios.  In particular, standard .NET operator overloads methods like ‘op_Equality’, ‘op_LessThan’, etc become difficult to use from F#, and performance can be significantly degraded, especially for non-primitive value types.

In F# 4.0, a new module of non-structural operators has been created.  By opening the new ‘NonStructuralComparison’ module, these operators are brought into scope and used instead of the default structural operators.

Async extensions to WebClient

Two new extension methods for System.Net.WebClient have been added to the FSharp.Control.WebExtensions module, allowing for easier usage of WebClient within F# async workflows:

  • WebClient.AsyncDownloadFile
  • WebClient.AsyncDownloadData

Interop APIs for Option

A handful of new convenience APIs have been added for converting between possibly-null .NET types and F# option types.

  • Option.toNullable: option:’T option -> Nullable<‘T>
  • Option.ofNullable: value:Nullable<‘T> -> ‘T option
  • Option.ofObj: value: ‘T -> ‘T option  when ‘T : null
  • Option.toObj: value: ‘T option -> ‘T when ‘T : null
  • Operators.tryUnbox : value:obj -> ‘T option
  • Operators.isNull : value:’T -> bool when ‘T : null

Quotation active pattern for Decimal values

There is now a dedicated active pattern in the runtime for deconstructing F# quotations which contain constant System.Decimal values.  This previously required some awkward matching on compiler-internal function names.

IDE

Script debugging

One of the most productivity-boosting aspects of the F# development process is the lightweight, iterative REPL experience.  As scripts and code snippets get larger and more complex, however, they can become difficult to debug. In the past, there was no way to attach the Visual Studio debugger directly to an F# script, so debugging options were limited and cumbersome: “printf debugging”, or refactoring one’s script into a full-fledged project.

In VS 2015, you can now debug F# scripts directly.  The debugger can be attached to the current F# Interactive session through context menus in the editor or the F# Interactive window itself.

debug

Integrated project up-to-date check

When building a multi-project solution, Visual Studio developers are accustomed to seeing a summary of how many project builds “succeeded”, “failed”, or were already “up-to-date.”  The F# project system never implemented the logic to detect the “up-to-date” status, so full builds were always launched.  This was a minor performance issue, and caused F# projects to always be reported as “succeeded” or “failed.”

In VS 2015, F# projects now fully support the integrated up-to-date check, and properly report their status in the build summary.

uptodate

 

Intellisense in object initializers

Intellisense integration has been improved for F# object initializer expressions.  Within an object initializer, the completion list (triggered by Ctrl+Space) will now contain the settable properties one can initialize.

objinit

Intellisense for named parameters

Similar to above, F# intellisense now gives auto-completions to assist with using named parameters to methods.

namedparam

Bug fixes around folder support

The F# project system does not implement native support for organizing code into folders.  The popular Visual F# Power Tools extension adds this functionality, but occasionally encounters bugs that require fixes to the project system itself.

Various fixes in this area have been made in VS 2015 in order to better support the Power Tools.  You can also now open F# project folders directly from solution explorer:

folder

 

 

We hope you enjoy the new capabilities in Visual F# 4.0!

-The @VisualFSharp Team