Detailed release notes for F# 188.8.131.52
A summary of the changes and additions for F# between 184.108.40.206 and 220.127.116.11 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.Notationhas been added, containing notational conveniences such as the values
Microsoft.FSharp.Math.Notation.Genericis also present.
- The primary type definitions have been moved to
- The modules previously called
MatrixOpsetc. are now called
- The suffixes have been dropped of value names like
getV. Instead qualified names such as
Vector.getshould be used.
- The names
createhave been changed to the more standard
- Some functions related to row vectors have been deleted
- A new module
Microsoft.FSharp.Math.Compatibility.MATLABhas been added, to contain functions that make programming in F# a little more like programming in MATLAB.
- The primary type definitions have been moved to
· Expression quotation library redesign and cleanup. Now called
· 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 =
|> 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)
// 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