Detailed release notes for F# 1.1.8.1

A summary of the changes and additions for F# between 1.1.5.2 and 1.1.8.1 is as follows:

· Expression Quotation now called Microsoft.FSharp.Quotations contains a range of functionality related to "lifted expressions", i.e. expression quotation, which is a form of meta-programming. This is still under development, and some important functionality is missing or incomplete, but is extensively used in the LINQ sample that is also available in the release.

  • Math library redesign. A new module Microsoft.FSharp.Math.Notation has been added, containing notational conveniences such as the values matrix, and vector. Microsoft.FSharp.Math.Notation.Generic is also present.
    • The primary type definitions have been moved to Microsoft.FSharp.Math.Types.
    • The modules previously called MatrixOps etc. are now called Matrix etc.
    • The suffixes have been dropped of value names like mapM; getV. Instead qualified names such as Matrix.map and Vector.get should be used.
    • The names create have been changed to the more standard init.
    • Some functions related to row vectors have been deleted
    • A new module Microsoft.FSharp.Math.Compatibility.MATLAB has been added, to contain functions that make programming in F# a little more like programming in MATLAB.
  • Renamed Microsoft.FSharp.Experimental.Reflection tp Microsoft.FSharp.Reflection.

· Expression quotation library redesign and cleanup. Now called Microsoft.FSharp.Quotations.

· HTML library manual pages now included in the release and on the Microsoft Research website.

· HTML documentation generation with fsc.exe. Look for the --html* flags in the advanced flags. Documentation is given using "///" comment markers prior to modules, types, values and exceptions.

· Bug Fixes - Fix some problems with the Visual Studio mode. Some files were missing.

· LINQ Sample. The sample samples\fsharp\FLinq shows how F# can work with the Language-Integrated-Query libraries currently under development at Microsoft.

· Source Release. source/... now finally includes all the source code to the F#, the library and the tools, as long promised. Much source has been included in previous releases, but we’d just never got around to including the whole bundle. NOTE: Some problems with the Makefile prevent it from compiling in this release – these will be fixed in the next release. General comment: The source has its many quirks and there are many things we will be cleaning up - if it's ugly then please be merciful and ignore it – we were in a rush.

· Visual Studio mode: (The source for the VS plugin is not yet included, though a crucial file 'fsharp/vs/service.ml' is - this has the key functionality that implements the line-by-line lexing, typechecking cache etc.)

· Argument name annotations for documentation purpose in signatures. Arguments can be labelled for documentation purposes, in signature files (.mli/.fsi) only. Note this is not the same os OCaml labelled arguments (which permit labels to be used at the callsite).

· First class uses of the 'unit' type now compiled to Microsoft.FSharp.Unit. Previous versions of F# compiled the unit type to System.Object. This has been changed to give better fidelity for runtime types, especially of function values. Note this will break C# 2.0 code that has not been using delegates of type System.Action</tt> as the way of creating function types.

· Library Updates as discussed recently on the F# list - see below

1. Adjust the signature of Idioms.using.

The current signature of Idioms.using is

val using: (_ :> System.IDisposable) -> (unit -> 'a) -> 'a

giving somewhat awkward usage patterns such as

let ts = new TransactionScope() in

using ts (fun () ->

<do something with ts>

)

In this release the signature becomes

val using: ('a :> System.IDisposable) -> ('a -> 'b) -> 'b

giving considerably more C#-like usage patterns such as

using (newTransactionScope ()) (fun ts ->

<do something with ts>

)

When translating code from C# we have found ourselves defining a new version of “using” to match the above, so it seems preferable, and something we should switch to sooner rather than later.

2. Standardize on the frequent use of “|>”

The operators “|>” and “>>” are already defined in MLLib.Pervasives as follows:

let (|>) x f = f x

let (>>) f g x = g (f x)

Over time it has become clear that use of these operators, and the “|>” operator in particular, is key to succinct expression of functional programming when using left-to-right type inference to resolve some name access base on type information (the technique F# uses to resolve method overloading and property accesses). Thus we will be using this operator far more extensively in F# code, tutorials and samples, and will assume that it’s use one of the first things an F# programmer learns.

For example, note how “a” and “ty” do not require type annotations in the following code to resolve the use of the “.” notation. This is because type information is propagated from the result type of GetAssemblies through to these binding sites.

let allMembers =

System.AppDomain.CurrentDomain.GetAssemblies()

|> Array.to_list |> List.map (fun a -> a.GetTypes()) |> Array.concat

|> Array.to_list |> List.map (fun ty -> ty.GetMembers()) |> Array.concat;;

(Now write that program in any other .NET language in 4 lines!)

Assuming familiarity with “|>”has some ramifications for library design, leading to some of the changes. In particular:

· Delete ‘transform’ , ‘foreach’ etc. in MLLib.List, MLLib.Array etc. These functions were added in an attempt to give left-to-right type inference, in the style above. However, they were never terribly effective at doing this. Furthermore the use of the name “foreach” clobbered the corresponding name in Idioms. They are best forgotten.

3. Include decent support for IEnumerable-related functions

· Add the following modules to MLLib (NOTE: not all functions are supproted in this release)

module IEnumerable

// The following functions work over the System.Collections.Generic.IEnumerable type

val length : #IEnumerable <'a> -> int

val hd : #IEnumerable <'a> -> 'a

val tl : #IEnumerable <'a> ->IEnumerable <'a>

val nth : #IEnumerable <'a> -> int -> 'a

val nonempty: #IEnumerable <'a> -> bool

val empty : unit -> IEnumerable<'a>

val init : (int -> 'a option) ->IEnumerable <'a>

val unfold : ('b -> ('a * 'b) option) -> 'b ->IEnumerable <'a>

val append : #IEnumerable <'a> ->#IEnumerable <'a> ->IEnumerable <'a>

val concat : #IEnumerable < #IEnumerable <'a> > ->IEnumerable <'a>

val exists : ('a -> bool) ->#IEnumerable <'a> -> bool

val for_all : ('a -> bool) ->#IEnumerable <'a> -> bool

val filter : ('a -> bool) ->#IEnumerable <'a> ->IEnumerable <'a>

val choose : ('a -> 'b option) ->#IEnumerable <'a> ->IEnumerable <'b>

val first : ('a -> 'b option) ->#IEnumerable <'a> -> 'b option

val find : ('a -> bool) ->#IEnumerable <'a> -> 'a

val tryfind : ('a -> bool) ->#IEnumerable <'a> -> 'a option

val iter : ('a -> unit) ->#IEnumerable <'a> -> unit

val iteri : (int -> 'a -> unit) ->#IEnumerable <'a> -> unit

val fold : ('b -> 'a -> 'b) -> 'b ->#IEnumerable <'a> -> 'b

val map : ('a -> 'b) ->#IEnumerable <'a> ->IEnumerable <'b>

val mapi : (int -> 'a -> 'b) ->#IEnumerable <'a> ->IEnumerable <'b>

val of_array: 'a array ->IEnumerable <'a>

val of_list : 'a list ->IEnumerable <'a>

val to_array: #IEnumerable <'a> -> 'a array

val to_list : #IEnumerable <'a> -> 'a list

// The following functions work over the System.Collections.IEnumerable type

// and are available on .NET 1.0/1.1

val untyped_fold : ('b -> 'a -> 'b) -> 'b -> #IEnumerable -> 'b

val untyped_iter : ('a -> unit) -> #IEnumerable -> unit

val untyped_map : ('a -> 'b) -> #IEnumerable -> IEnumerable

val untyped_filter: ('a -> bool) -> #IEnumerable -> IEnumerable

val untyped_to_list: #IEnumerable -> 'a list

· Mark the following as obsolete.

Idioms.foldeach (replaced by IEnumerable.fold_untyped)

Idioms.transform (replaced by IEnumerable.map_untyped)

Idioms.foldeachG (replaced by IEnumerable.fold)

Idioms.transformG (replaced by IEnumerable.map)

Idioms.foreachE (never needed – all relevant types implement IEnumerable)

Idioms.foldeachE (never needed – all relevant types implement IEnumerable)

Idioms.transformE (never needed – all relevant types implement IEnumerable)

Idioms.foreachEG (never needed – all relevant types implement IEnumerable)

Idioms.foldeachEG (never needed – all relevant types implement IEnumerable)

Idioms.transformEG (never needed – all relevant types implement IEnumerable)

This leaves the following in Idioms:

val foreach : #System . Collections . IEnumerable-> ('a -> unit) -> unit

val foreachG: #System . Collections . Generic . IEnumerable <'a> -> ('a -> unit) -> unit

Rationale: The purpose of Idioms is to hold F# representations of idioms in .NET, C# and other languages. It should be comprehensible to beginner F# users. The above functions were added in a bit of a hurry and simply shouldn’t be in Idioms, since their purpose is to offer a consistent set of folding and mapping operations over both the generic and non-generic (untyped) IEnumerable and IEnumerator types. Much preferable is a module in MLLib that holds these operations using the consistent MLLib naming scheme (iter, fold, map etc.).

Note: the LINQ initiative will offer further platform-standard functionality similar to the above, and when the final version of LINQ is released we will support a namespace such as Microsoft.FSharp.Bindings.Linq which maps the Linq operators into F#. Having a half-baked version of this stuff in Idioms doesn’t do anyone any good. However we can’t wait for the release of Linq to fix this sort of thing, and in any case Linq uses naming conventions which are different to F# (select for map, where for filter etc.).

· Mark as obsolete the very thinly populated and undocumentedIdioms.IEnumerable, Idioms.IEnumerator. These were again added in a hurry leading up to the last release and are again best forgotten.

4. Include consistently named support for Enum-related functions

· Add the following module to MLLib

moduleMicrosoft . FSharp . MLLib . Enum

///Convert an enumeration value to an integer. The argument type is inferred from context.

val to_int: 'a -> int when 'a :> System . Enum

///Convert an integer to an enumeration value. The result type is inferred from context.

val of_int: int -> 'a when 'a :> System . Enum

///Combine enum values using 'logical or'. The relevant enumeration type is inferred from context.

val combine: 'a list -> 'a when 'a :> System . Enum

///Test if an enumeration value has a particular flag set, using 'logical and'.

///The relevant enumeration type is inferred from context.

val test: 'a -> 'a -> bool when 'a :> System . Enum

· Mark the following as obsolete.

Idioms.EnumToInt (replaced by Enum.to_int)

Idioms.IntToEnum (replaced by Enum.of_int)

Idioms.CombineEnumFlags (replaced by Enum.combine)

Idioms.TestEnumFlag (replaced by Enum.test)

Rationale: The purpose of Idioms is to hold F# representations of idioms in .NET, C# and other languages. The above functions are not particularly idioms in any other .NET language – they just represent things where you have to be a bit more explicit in F#. They date from the day when Idioms was a sink for “anything which you needed to do with a runtime check”. Their naming is not particularly consistent with any other style. Nor are they particularly easy to find.

It is much preferable to add a module to MLLib that holds these operations using the consistent MLLib naming scheme (to_int, of_int etc.).

Note: A future version of F# may support + etc. on enum types.

Bug Fixes. Various minor fixes.

 511    F# Interactive  1   0   errors raised during optimization exit fsi.exe
522   F# Interactive  1   1   fsi bug with operator names
523  F# Interactive  1   0   Automatic binding to a relative path (or the current directory) fails
532    F# VS Plugin    1   1   VS -I and -r relative paths are relative to somewhat random working directoy of VS process rather than the project/file working directory
534    F# VS Plugin    2   1   off-by-one error in VS mode balloon tips
525 F# VS Plugin    1   1   visual studio prior inputs with unicode signature are not being parsed correctly
537 F# Docs         1   1   Abbreviated types appearing in XMLDoc files, also 'unit'
543 F# Language 1   1   printing "List" and "Option" for types generated by uses of constructors looks gross
433 F# Compiler 2   2   Represent "unit" as a real type rather than abbreviating to "obj"
453    F# Compiler 2   2   print_any - no printing of repeated terms - no print depth/width controls
505    F# Language 1   0   implement a way to name arguments - crucial documentation
529    F# Compiler 1   0   differing orders of fields for records in signatures and implementations cause problems for record constructors and "with"
549   F# VS Plugin    1   0   VS redirecting stdout to Output window interferes with stdin
552 F# VS Plugin    1   1   VS mode show 2 resolutions for .NET types
553    F# VS Plugin    1   1   VS Mode method tips bounce back to first entry every time the "down" key is pressed (reported by Artem - thanks Artem!)
554  F# VS Plugin    1   1   Balloon Tips not showing XMLDoc help text for methods and types
555  F# VS Plugin    1   1   Intellisense not showing signatures and overloads for .NET constructors.
556 F# Documents    1   1   Incorrect XMLDoc signatures being generated for generic methods and some other generic gadgets
539   F# Interactive  1   0   compile F# Interactive on .NET 1.0
560   F# VS Plugin    1   1   TAB in VS mode doesn't activate completion
561   F# Language 1   1   Module abbreviations not permitted in signatures
563 Abstract IL 2   2   AbstractIL library contains duplicate hashtable modules etc.
562 F# Library  1   1   printf %s formats do not permit padding specifications
564   Abstract IL 1   1   Abstract IL library module names need to be much more sensibly organized