Release Notes for the F# October 2009 release


 


(These notes apply to the F# October 2009 CTP update and Visual Studio 2010 Beta2)


 


Summary



  • Release


    • F# in Visual Studio2010 Beta2 can build applications for .NET 2.0/3.0/3.5/4.0 and Silverlight 2/3. 

    • Updated F# CTP for Visual Studio 2008

    • F# PowerPack available as part of the CTP Update, and can be used with either CTP Update of VS2010 Beta2

  • F# Language


    • OverloadID no longer required for defining overridden methods

    • Require module/namespace at top of files

    • ‘comparison’ and ‘equality’ constraints

    • Core conversion operators use .NET standard op_Implicit/op_Explicit instead or ToInt32, etc.

    • Support for global namespace qualification, “global.A.B.C” and “namespace global”

    • More flexibility in defining yield! and return! in computation expressions using YieldFrom and ReturnFrom

    • Extension methods can participate in overload resolution

    • Support for volatile fields using [<Volatile>]

    • Support for letting F# types allow “null” using [<AllowNullLiteral>]

    • Interface implementations can now be inherited

    • Private type abbreviations (type private X = int)

    • More flexibility for list literals and subtyping

    • Recursive type inference improvement

  • F# Compiler


    • HTML doc generation moved from compiler to PowerPack

    • Discriminated Union code generation provides simpler .NET view

  • F# Core Libraries


    • Complete the under_score -> camelCase name standardization, of_list -> ofList

    • Async API Additions for Web Requests

    • Async API Additions  for Reactive Applications

    • Array2D enables easily creating 2D arrays

    • Observable module

    • Version-stable serialization of Map and Set

    • [.NET 4.0] Lazy, CancellationToken, BigInteger in .NET4.0

    • CompiledName used to ensure .NET view is C#/VB friendly

  • Visual Studio


    • Multitargeting for VS2010: 2.0-4.0 + Silverlight

    • Error list improvements

    • Much improved debug display of unions and other F# types.

    • F1 support

  • F# Interactive


    • #load .fsx

  • F# PowerPack


    • Async additions

    • FsHtmlDoc.exe

  • Miscellaneous


    • Deletion of features deprecated in previous F# releases

    • Plus many minor fixes and improvements


F# Language


OverloadID no longer required for defining overridden methods


 


Overloaded methods can now be defined without the need for the OverloadID attribute. 


 


type Foo() =


    member this.CountChars(s : string ) = s.Length


    member this.CountChars(c : char) = 1


Require module/namespace at top of files


 


All .fs files, except the last file in an application project, must begin with either a module or namespace declaration.  Previously files were put in a default module named after the file.  Files can be structured to define an F# module:


 


module Widgets


 


type T() =


    member this.X = 12


let x = 12


Or a namespace:


namespace Widgets


 


type T() =


    member this.X = 12


Nested modules and namespace may be defined as before.


Note: Code of the form


namespace Widgets


 


module Module1



should be rewritten as


 


module Widgets.Module1


 



 ‘comparison’ and ‘equality’ constraints


 


Two new F#-specific  constraints  are added:


ty : comparison


ty : equality


Note: Equality includes “hashing”


 


A type satisfies ty : equality under these conditions


Ø  if the type has dependencies T1, …, TN then each of these must satisfy equality; AND


Ø  the type doesn’t have the NoEquality attribute; AND


Ø  the type is not inferred to be NoEquality (for record, union and struct types)


A type satisfies ty : comparison under these conditions


Ø  if the type has dependencies T1, …, TN then each of these must satisfy comparison; AND


Ø  the type doesn’t have the NoComparison attribute; AND


Ø  the type implements IComparable, or the type is an array/IntPtr/UIntPtr; AND


Ø  the type is not inferred to be NoComparison (for record, union and struct types)


One ramification of this is that most .NET types satisfy equality, even if this defaults to reference equality.


 


These constraints are used on some common parts of the F# library:


 


    val max        : ‘T[] -> ‘T        when ‘T : comparison


    val min        : ‘T[] -> ‘T        when ‘T : comparison


    val sort       : ‘T[] -> ‘T[] when ‘T : comparison


    val sortInPlace: ‘T[] -> unit      when ‘T : comparison


    val maxBy      : (‘T -> ‘Key) -> ‘T[] -> ‘T when ‘Key : comparison


    val minBy      : (‘T -> ‘Key) -> ‘T[] -> ‘T when ‘Key : comparison


    val sortBy     : (‘T -> ‘Key) -> ‘T[] -> ‘T[] when ‘Key : comparison


    val sortInPlaceBy: (‘T -> ‘Key) -> ‘T[] -> unit when ‘Key : comparison


    val countBy    : (‘T -> ‘Key) -> seq<‘T> -> seq<‘Key*int> when ‘Key : equality


    val distinct   : seq<‘T> -> seq<‘T> when ‘T : equality


    val distinctBy : (‘T -> ‘Key) -> seq<‘T> -> seq<‘T> when ‘Key : equality


 


 


    val ( < )   : ‘T -> ‘T -> bool when ‘T : comparison


    val ( > )   : ‘T -> ‘T -> bool when ‘T : comparison


    val ( >= )  : ‘T -> ‘T -> bool when ‘T : comparison


    val ( <= )  : ‘T -> ‘T -> bool when ‘T : comparison


    val ( = )   : ‘T -> ‘T -> bool when ‘T : equality


    val ( <> )  : ‘T -> ‘T -> bool when ‘T : equality


    val compare : ‘T -> ‘T -> int  when ‘T : comparison


    val hash    : ‘T -> int        when ‘T : equality


    val max     : ‘T -> ‘T -> ‘T   when ‘T : comparison


    val min     : ‘T -> ‘T -> ‘T   when ‘T : comparison


 


In some cases, code may need to be updated to take into account these constraints.


 


F# types may indicate how they participate in generic comparison or equality using attributes NoEquality/Comparison, StructuralEquality/Comparison. These are used on some F# library types, for example:


 


   


    [<NoEquality>]


    [<NoComparison>]


    type Async<‘T>


 


In some circumstances it is also useful to make equality and comparison of a collection type conditional on a type parameter having equality/comparison. This is done using the EqualityConditionalOn and ComparisonConditionalOn attributes:


 


    type Set<[<ComparisonConditionalOn>] ‘T  when ‘T : comparison>


 


These attributes are inferred for structural types:


 


    // inferred: [<EqualityConditionalOn>] for T1, T1


    // inferred: [<ComparisonConditionalOn>] for T1, T2


    type Choice<‘T1,’T2> =


      | Choice1Of2 of ‘T1


      | Choice2Of2 of ‘T2


 


Two new functions are available to access an “Unchecked” implementation of equality and comparison that is equivalent to the regular equality and comparison implementations, as used in previous implementations of F#, but may be used with any types without constraint


 


    Unchecked.compare

    Unchecked.equals

 


 


Further details of the equality/comparison constraint feature will be contained in the updated F# specification, to be released after these notes are posted.


Core conversion operators use .NET standard op_Implicit/op_Explicit instead or ToInt32, etc.


Overloaded conversion operators such as ‘int’, ‘char’ and ‘float’ which previously provided custom overloading via ToXXX conversion functions now use .NET standard op_Implicit/op_Explicit instead.  Any type defining an op_Implicit or op_Explicit returning the expected type can be used with these conversion operators.


type MyInt(x : int) =


    member this.X = x


    static member op_Explicit(myint : MyInt) = myint.X


 


let myInt = new MyInt(3)


 


// The ‘int’ conversion function calls the op_Explicit method on MyInt


let oldInt = int myInt


 


Support for global namespace qualification, “global.A.B.C” and “namespace global”


Types can now be defined in the .NET “global” namespace using:


namespace global


 


type T() =


    member this.X = 12


 


Additionally, in cases where partially-qualified names clash, name lookup can be qualified to the global namespace environment:


 


let line = global.System.Console.ReadLine()


 


More flexibility in defining yield! and return! in custom computation expressions


To support more flexible uses of computation expressions, the two computation expression forms yield! and return! are now de-sugared as follows:


yield! expr    ->   builder.YieldFrom expr


return! expr   ->   builder.ReturnFrom expr


 


Extension methods can participate in overload resolution


 


Extension methods can be defined as overloads of existing methods.  These are given a lower priority in overload resolution.  See the F# spec for full details.


 


type System.String with


    member this.Split(seps : string) =


        this.Split(


            [|seps|],


            System.StringSplitOptions.RemoveEmptyEntries)


       


let parts = “a b c  d”.Split(” “)


 


Support for letting F# types allow “null” using [<AllowNullLiteral>]


 


Types defined in F# do not generally allow the use of the ‘null’ literal as a proper value.  However, null values can be passed in for these types from non-F# .NET callers, and sometimes it is necessary to write F# types that naturally do support a null proper value. 


type T1() =


    member this.X = 12


 


[<AllowNullLiteral>]


type T2() =


    member this.X = 12


 


let t1 : T1 = null // Error


let t2 : T2 = null // No error


 


Interface implementations can now be inherited


 


Interfaces implemented by inherited classes can be used to satisfy interface implementation requirements on a derived class. Code such as the following now compiles without the need to explicitly implement I1 in C2.


 


type public I1 =


    abstract V1 : string


   


type public I2 =


    inherit I1


    abstract V2 : string


   


type public C1() =


    interface I1 with


        member this.V1 = “C1”


 


type public C2() =


    inherit C1()


    interface I2 with


        member this.V2 = “C2”


More flexibility for list literals and subtyping


List and array literals may now be used to create collections from elements that are subtypes of the collection element type.  For example:


 


let myControls: (Control list) = [ new Button() ; new TextBox() ]


 


F# Compiler


HTML doc generation moved from compiler to PowerPack


The –generatehtml compiler option has been removed, and the functionality moved into a separate tool in the F# PowerPack (see below).  This enables decaoupling documentation generation from compilation, and more customization of doc generation.


F# Binary Compatibility 2.0-4.0


 


 


As we have discussed with the F# community, full ongoing binary compatibility is expected starting with the version of F# that comes with the Visual Studio 2010 RTM release.


 


This release has taken crucial steps towards the F# team goal of ensuring binary compatibility for components across .NET 2.0-4.0. For example, in previous releases different copies of the F# Power Pack were required for .NET 2.0-3.5 and 4.0. However, in this release we have one version of the Power Pack which can be used on both .NET 2.0-4.0 (installed via the CTP MSI or ZIP).


 


If you are authoring F# binary components, you can now build binary compatible components in a similar way. There are some important caveats to this due to two missing type forwarders in FSharp.Core.dll, notably


 


Ø  DLLs using Array2D.* or 2D arrays in public API surface area are not automatically binary compatible across 2.0/4.0. With care these DLLs can be made binary compatible across 2.0/4.0, and this has been done for the F# Power Pack,  but normally these APIs will not be binary compatible across 2.0/4.0 until Visual Studio 2010 RTM


 


Ø  Likewise DLLs using F# lazy values (System.Lazy<_>) are not automatically binary compatible. With care, these DLLs can be made binary compatible across 2.0/4.0 by using a private copy of the F# lazy implementation from .NET 2.0, and this has been done for the F# Power Pack. However in the absence of special attention these APIs will not be binary compatible across 2.0/4.0 until Visual Studio 2010 RTM


 


Binary compatibility can be checked in part by running peverify for .NET 2.0 and .NET 4.0 after installing Visual Studio 2010, a version of Visual Studio 2008 and the F# CTP.


 


F# Core Libraries


 


 


 


Async API Additions for Web Programming


 


The extension methods webClient.AsyncDownloadString and webRequest.AsyncGetResponse are now defined in FSharp.Core.dll, and accessed via


 


open Microsoft.FSharp.Control.WebExtensions


 


For example:


 


open System.Windows.Forms


open System.Net


open System.IO


open Microsoft.FSharp.Control.WebExtensions


 


/// Fetch the contents of a web page, asynchronously


let httpAsync (url:string) =


    async { let req = WebRequest.Create(url)            


            let! resp = req.AsyncGetResponse()


            // the rest is a callback


            use stream = resp.GetResponseStream()


            use reader = new StreamReader(stream)


            return reader.ReadToEnd()  }


 


 


 


 


Async API Additions  for WinForms, WPF, Silverlight  and ASP.NET applications


 


The Async API has a number of new additions and design extensions to better enable writing “single-primary-thread-of-control” reactive applications using F# asyncs. This is a commonly used idiom for Windows Forms, WPF, Silverlight  and ASP.NET programming.


 


These applications are I/O parallel, but only use CPU parallelism in constrained ways. In this kind of application, CPU processing is done on a single thread of control, but multiple I/O requests may be overlapped.


 


In .NET, these applications will typically have a non-null, dedicated value for System.Threading.SynchronizationContext.Current on the main “thread”.


Waiting for .NET Events


 


The method Async.AwaitEvent is now defined in FSharp.Core.dll. This method runs the continuation of the async the first time .NET event fires.


 


open System.Windows.Forms


 


let form = new Form(Visible=true,TopMost=true)


 


async { let! firstClick = Async.AwaitEvent form.Click


        form.Text <- “I got clicked once!”


        let! nextClick = Async.AwaitEvent form.Click


        form.Text <- “I got clicked twice!” }


|> Async.StartImmediate


 


Starting Asyncs on the Current Thread


 


The methods Async.StartImmediate and Async.StartWithContinuations are now defined in FSharp.Core.dll. These methods start the async immediately on the current thread, until the first point where the thread yields through an operation such as Async.AwaitEvent or an I/O operation.


 


These methods are particularly useful for starting async operations on the GUI or ASP.NET thread.


 


A use of StartImmediate is shown above.


 


Automatic Return to Context


 


F# library async I/O and waiting primitives can now be used from GUI or ASP.NET threads in a simpler fashion. Conceptually, if you start an async I/O operation or an async wait operation on a GUI thread, then it will “complete” on the GUI or ASP.NET thread.


 


If a primitive async operation is started on a thread where SynchronizationContext.Current  is set, then the continuation of such an async is posted using SynchronizationContext.Post.  


 


In the following example the overall async is started on the GUI thread using StartImmediate. As the click happens and the asynchronous fetches of the web pages return, the overall async is in each instance continued on the GUI thread.  This means the GUI components can be safely updated from the async.


 


open System.Windows.Forms


 


let form = new Form(Visible=true,TopMost=true)


 


async { let! firstClick = Async.AwaitEvent form.Click


        form.Text <- “I got clicked!”


        let! firstPage = httpAsync “http://www.google.com”


        form.Text <- “I got the first page!”


        let! secondPage = httpAsync “http://www.bing.com”


        form.Text <- “I got the second page!” }


|> Async.StartImmediate


 


F# asyncs built using the following API operations implement “automatic return to context”:


  


Async.Parallel


Async.Sleep


Async.AwaitEvent


Async.AwaitIAsyncResult


Async.AwaitTask


Async.AwaitWaitHandle


Async.FromBeginEnd


Async.FromContinuations


 


type System.Net.WebRequest with


    member AsyncGetResponse()


 


type System.Net.WebClient with


    member AsyncDownloadString()


 


type System.IO.Stream with


    member AsyncRead()


    member AsyncWrite()


 


Async API Renamings


System.Threading.AsyncSleep         ->    Async.Sleep


extension waitHandle.AsyncWaitOne   ->    Async.AwaitWaitHandle


extension waitHandle.AsyncWaitOne   ->    Async.AwaitWaitHandle


Async.BuildPrimitive                ->    Async.FromBeginEnd


Async.SwitchToGuiThread             ->    Async.SwitchToContext


Async.RunWithContinuations          ->    Async.StartWithContinuations


 


Complete the under_score -> camelCase name standardization, of_list -> ofList


 


The naming normalization across the F# core libraries is finalized in this release, with the following removals of underscores and abbreviations:


to_list      -> toList


to_array     -> toArray


to_seq       -> toSeq


of_list      -> ofList


of_array     -> ofArray


of_seq       -> ofSeq


of_nativeint -> ofNativeInt


to_nativeint -> toNativeInt


hd           -> head


tl           -> tail


 


Observable module and F# events


 


The IObservable and IObserver interfaces provide a general interface over observable data, which can be easily composed.  These interfaces are provided in .NET4.0, and are available in F# for .NET2.0. 


1st class events in F# now implement the IObservable interface, enabling them to interoperate with other IObservable programming models.  A new Observable module in the F# library provides compositional functions for manipulating general Observable data:


    Observable.merge


    Observable.map


    Observable.filter


    Observable.partition


    Observable.split


    Observable.choose


    Observable.scan


    Observable.add


    Observable.subscribe


    Observable.pairwise


 


array2D enables easily creating 2D arrays


 


A new ‘array2D’ function converts data into 2d arrays:


 


let matrix = array2D [[1;2;3];


                      [2;3;4];


                      [3;4;5]]


 


 [.NET 4.0] Lazy, CancellationToken, BigInteger in .NET4.0


 


Some F# types have moved into mscorlib in .NET4.0, making it easier to reuse these types between F# and other .NET languages.  On .NET2.0, these F# types have been moved to corresponding namespaces within FSharp.Core.dll.  The following important F# types have moved to System namespaces:


Lazy -> System.Lazy


Tuple -> System.Tuple


BigInt -> System.Numerics.BigInteger


AsyncGroup -> System.Threading.CancellationTokenSource and System.Threading.CancellationToken


 


CompiledName used to ensure .NET view is C#/VB friendly


 


The .NET-visible names of types and members in FSharp.Core.dll are modified to align with standard .NET naming conventions.  This makes it easier to use FSharp.Core defined types from other .NET languages.  For example:


Seq.iteri -> Microsoft.FSharp.Collections.SeqModule.IterateIndexed


failwith -> Microsoft.FSharp.Core.Operators.FailWith


Visual Studio


 


[VS2010] Multitargeting support for 2.0-4.0 + Silverlight


 


With VS2010, F# users can target .NET 2.0, 3.0, 3.5, 3.5 Client, 4.0 and 4.0 Client.  F# libraries can also be built targeting Silverlight 2 and 3.  F# libraries built against .NET2.0 can also be used as part of F# applications targeting later versions of .NET.


 


Error list improvements


 


The Visual Studio error list is populated with F# errors both during editing of F# files, and during building of F# projects.  This release ensures that errors are tracked between these two sources when they are available in both.


 


F1 support


 


F1 contextual help support is available in the F# editor.  This will open documentation for the type or member reference at the cursor.  In addition, in VS2010, F1 help on F# keywords or F# library functions will go to the new MSDN documentation on these subjects.


F# Interactive


 


#load .fsx


 


When building complex F# scripts, it is sometimes necessary to split a script into multiple .fsx files.  F# scripts now support the ability to load other F# scripts, enabling factoring of scripts into source components. 


F# PowerPack


 


FsHtmlDoc.exe


 


A new tool called fshtmldoc.exe is now available in the F# Power Pack. This replaces the HTML doc functionality in the F# compiler. The command line options are shown using “fshtmldoc.exe –help”


 


 

Comments (1)

  1. Oliver Sturm says:

    With OverloadID deprecated, how do I overload on return type now?

    This used to work:

       member x.Walk() = 42

       [<OverloadID("WalkReturningString")>]

       member x.Walk() = "A String"