F#, the F# Compiler and the F# Visual Extensions, Version 1.9.4.19

Welcome to F#. F# is a programming language for the .NET platform with a design based on the ML programming language with extensions to access .NET libraries. This release contains

Full details can be found at the F# website. There you can find details about F# resources and community sites. You may be interested in tracking Don Syme's F# blog and/or blogging about your experiences with using F#.

Installation:

Using and Learning:

Troubleshooting:

Requirements

Using F# with Mono

You may run F# programs in conjunction with other CLI implementations such as Mono. Please read the notes below. Some more information is available at the F# Wiki.

Changes

Changes between v1.9.4.17 and 1.9.4.19

F# On Mono

Library

        type System.Net.WebRequest with
            member x.GetResponseAsync() =
                Async.BuildPrimitive(x.BeginGetResponse, x.EndGetResponse)

Bugs fixed

2033	F# Compiler doesn't work with type forwarders found in .NET Framework 3.5 SP 1 Beta1

Changes between v1.9.4.15 and 1.9.4.17

Library

Bugs fixed

2033	Code Dom Error Reporting not working in 1.9.4.15, reported by Tomas Petricek (thanks Tomas!)
2062	Inapplicable error message on attributes on method parameter, reported by David Crocker (thanks David!)
2101	Performance regression with regard to inlining, reported by Stephan Tolksdorf (thanks Stephan!)
2108	Fix intellisense regression in 1.9.4.15 due to mistaken release of experimental code, reported by Howard Mansell (thanks Howard!)
2125	Stack overflow in structural equality test on 64-bit CLR, reported by Stephan Tolksdorf (thanks Stephan!) 
2128	Regression:  cannot convert the following F# Quotation to a LINQ Expression Tree

Changes between v1.9.3.14 and 1.9.4.15

Summary

Language

Library

Tools

Language Enhancements: Design Extensions and Changes

Symmetric Operator Overloading

F# uses a form of type-directed operator overloading. (Type-directed operator overloading means that operators such as '+' resolve to different implementations depending on the static types of the two arguments.) Previous releases of F# used asymmetric, type-directed overloading that placed more emphasis on the type of the left argument rather than the type of the right argument. For some time it has been recognized that this form of operator overloading is somewhat unintuitive. This release switches this to use symmetric operator overloading. For example, consider the following cases:

    let f1 x y = x + y              //: int -> int -> int
    let f2 (x:float) y  = x + y     //: float -> float -> float
    let f3 x (y:float)  = x + y     //: float -> float -> float
    let f4 (x:matrix) y = x + y     //: matrix -> matrix -> matrix
    let f5 x (y:matrix) = x + y     //: matrix -> matrix -> matrix
    let f6 (x:matrix) (y:vector) = x * y    //: matrix -> vector -> vector

These indicate that operator overloading resolves independent of whether the known type information is associated with the left-hand or right-hand argument of the operator.

The two principles that now form the basis of F# operator overloading are

Resolution of an operator such as + is performed against a set of potential overload resolutions derived from the left and right hand argument types. For example, when resolving a constraint

    static member (+) : float * matrix -> ?

The relevant operator overloads are drawn from the float and matrix types. At some points in inference (indeed very frequently) we have incomplete information about the types involved, e.g.

    static member (+) : float * ? -> ?

In these cases it is important to note that later type information may discover additional nominal information, e.g. to resolve the constraint to

    static member (+) : float * matrix -> matrix

In more detail,

    open Microsoft.FSharp.Math
    let f7 (x:Matrix<_>) y = x + y
Conditional Method Calls and assert

Conditional method calls are a .NET feature where a call to particular methods marked with System.Diagnostics.ConditionalAttribute are only executed if a conditional compilation symbol such as DEBUG is defined. One common example of this is System.Diagnostics.Debug.Assert. F# now supports conditional method calls.

As a result of this change, calls to System.Diagnostics.Debug.Assert may no longer "trigger" in your code.

Uses of the assert function are now treated as if they are calls to System.Diagnostics.Debug.Assert. This means expressions such as assert (1=2) will not fire in your code unless --define DEBUG is specified. This follows standard .NET software engineering practice.

One exception is made for the syntactic expression form assert(false). This is given a special type in F# and OCaml, i.e. has variable return type not unit. This allows it to be used as a "cannot happen" signifier. In this case, if --define DEBUG is not specified then an AssertionFailure exception is raised in order to halt execution. If --define DEBUG is specified then System.Diagnostics.Debug.Assert, and if the assertion is ignored and execution continues then the AssertionFailure exception is raised in order to halt execution.

Additional nullness checking

.NET is an object-oriented platform and thus includes the notion of null values for reference types. However, the use of null values is, in general, discouraged in F# programming. While it is possible to create null values for reference types, one of the design aims of F# is that this is not a commonly used technique and that, when used, the programmer is made aware of this.

In previous release of F#, creating null values of F# types was relatively easily, e.g. through the commonly used unbox function. This technique, however, will now raise a NullReferenceException. For example, the following code will now raise a NullReferenceException:

    type MyRecord = { f : int }
    let x = unbox<MyRecord>(null:obj)

This implemented via the use of efficient helper functions related to the types involved.

This change also eliminates several somewhat subtle inconsistencies with regard to types that use null as a valid representation. For example, the option type uses null to represent the None option. Unboxing a null value to one of these types now correctly succeeds and returns a valid value of the type.

In more detail, there are four kinds of types for F#:

The behaviour of the unbox and type test primitives of F# now treat these different categories appropriately.

Note that null is still used as a representation for some F# values, in particular None option values. In this case, the value doesn't carry runtime type information in the manner of other object values, and so type tests against such a value are inherently imprecise. This is correct and expected behaviour for these types.

If necessary, null and default values may be generated by calling the new library function Unchecked.defaultof<type>, a helper function specifically designed to make uses of arbitrary null and default values for F# types more traceable in code.

    type MyRecord = { f : int }
    let x = Unchecked.defaultof<MyRecord>
Minus syntax

Expressions of the form expr -expr, e.g. x -y now give a deprecation warning asking you to rewrite these as either expr - expr or expr-expr. This is to make room for a future design change.

New reserved keyword

The keyword global has been reserved for future use by F# code

Smaller Design Changes

'base' variables must now be called 'base'.

A deprecation warning is now given if this is not the case. In a future release of F# base variables will necessarily be called 'base'.

Intrinsic members take predence over extension members .

Previously extension members were taking priority over intrinsic members in base classes. This has now been corrected.

Generic Equality now uses Object.Equals

Uses of the generic equality operator (=) and related operators are now implemented via calls to System.Object.Equals.

Downcasting For Interface Types.

The conversion operator expr :?> type can now be used to convert an interface or non-sealed class type to any other interface type. This matches the C# behaviour of this operator, with the exception that conversions from variable types are not permitted: in that case the expression should first be converted to an object using box.

Handle Optional Arguments Correctly when using a method as a first class function value.

As has been reported several times in bug reports, when operations such as Async.Run which take optional arguments are used as first-class values the resulting function value previously required the optional argument be made explicit. This has now been changed, and the optional argument is dropped instead.

Change .[] overload resolution behaviour.

Previously, the resolution of the expr.[expr] operator did not apply operator overloading rules. This led to incompletenessed where the operator could not be used in conjunction with certain C# types. This has now been corrected.

Deprecate the Unicode symbols in the language.

The Unicode symbols for quotations have been deprecated. Instead, the ASCII symbols <@ @> and the prefix operators % and %% should be used instead.

Language Feature Completions

Sealed attribute . This attribute may be added to class types to mark them 'sealed', i.e. no base types.

    [<Sealed>]
    type C(x:int,y:int) = 
        member this.X = x
        member this.Y = y
        member this.Sum = x+y

AbstractClass attribute . This attribute may be added to class types to mark them 'abstract', i.e. missing implementations of some members, and/or with constructors that can't be used directly

    [<AbstractClass>]
    type C(x:int,y:int) = 
        abstract X : int
        abstract Y : int
        abstract GetSum : int -> int

typeof may be used in attributes, deprecate (type ...) syntax

    [<SomeAttribute(typeof<int>)>]
    type C(x:int,y:int) = 
        abstract X : int
        abstract Y : int
        abstract GetSum : int -> int

Decimal literals now implemented. For example, 120.00M. The decimal conversion function is now also supported amongst the standard set of conversion functions, and decimal is no longer a keyword.

    let pocketMoney = 0.25M
    let GDP = 12416505085952.00M

Supply Named and Optional Arguments to COM methods. It is now possible to use the F# optional argument mechanism to supply arguments to COM methods. This is very important when working with Excel and Word Primary Interop Assemblies. For example,

    chartobject.Chart.ChartWizard(Source = range5,
                                  Gallery = XlChartType .xl3DColumn,
                                  PlotBy = XlRowCol.xlRows,
                                  HasLegend = true,
                                  Title = "Sample Chart",
                                  CategoryTitle = "Sample Category Type",
                                  ValueTitle = "Sample Value Type")
   

Here 4 arguments have been omitted from the programmatic specification of an Excel chart.

Allow construction of delegates taking byref arguments

Library Enhancements

fold_left performance improvements.

A number of library functions that take binary functions have been optimized. Many thanks to the folk at Morgan Stanley for sugesting these!

Collections that previously threw IndexOutOfRangeException now throw KeyNotFoundException.

The OCaml-compatibility exception type Not_found is now mapped to System.Collections.Generic.KeyNotFoundException, rather than System.IndexOutOfRangeException. This means a number of F# functions now raise KeyNotFoundException instead of IndexOutOfRangeException. In the rare case where you explicitly catch IndexOutOfRangeException in your code you will get a warning and may need to adjust your exception handling accordingly. This change was made because IndexOutOfRangeException is a CLR-reserved exception which should not be raised in user or library code.

Addition of the 'enum' overloaded function.

The enum function can be used to convert integers to enumerations. Likewise, the function int32 can be used to convert back to an integer.

    let sunday  = System.DayOfWeek.Sunday
    let monday  = enum<System.DayOfWeek> 1
    let tuesday = enum<System.DayOfWeek> 2
   

Deprecate the Enum.to_int and Enum.of_int functions.

These can be replaced by uses of enum and int32 respectively.

Access control checking for modules and types implemented.

That is, private and internal annotations on modules and types are now implemented. Previously these gave a warning.

Deprecate the use of string.CompareTo in favour of System.String.CompareTo.

This makes room for a planned design change to add a conversion function called string.

Deprecate the IEnumerable module in favour of Seq.

Rename MailboxProcessor.PostSync to MailboxProcessor.PostAndReply, deprecating the old name

Deprecate the CompatArray and CompatMatrix modules when used with .NET 2.0.

Future releases of F# will make .NET 2.0 the default. These modules are only required when using .NET 1.x. When using .NET 2.0 and above, uses of these modules can be replaced by uses of Array and Array2 respectively.

Deprecate the truncate OCaml-compatibility function.

Instead you should use the synonymous for int_of_float or the F# conversion function int, applied to float values. The design of other F# conversion functions and operators means it is much more natural for truncate be an overloaded function applying to a range of numeric types. Thus a deprecation warning is now given on the use of the existing truncate function.

Make 'lock' function safer: may now only take reference types.

Tool Enhancements

Counter Examples from Incomplete Pattern Matches. For example,

    let f x = 
        match x with 
        | 1 -> 7
        | 2 -> 49


    stdin(12,14): warning FS0025: Incomplete pattern matches on this expression. The value '3' will not be matched

Note: There is actually one known bug here, where incomplete matches on union types do not always give a valid counter example. This is being addressed.

Implement redundancy checking for isinst patterns. That is, duplicate or redundant type tests in patterns will now be reported as warnigns.

Many Improved Error Messages

Enhancements to F# Interactive in Visual Studio

Ctrl-C now copies, Ctrl-. used for Interrupt. When used in Visual Studio, it is natural for Ctrl-C to be interpreted as 'copy'. This Ctrl-. ('Control-Stop') is now used for interrupt.

Menus supported. The interrupt, select-all, copy, paste and clear options are now available from the right-click menu.

Bugs fixed

1171    F# Compiler         bug binding to a SOAP dll
1109    F# Compiler         Make assert a function
1325    F# Compiler         Enums of chars are not accepted by F# Interactive
1316    F# Compiler         Throw away invalid paths (#r) in FSI
1341    F# Compiler         Compiler should reject explicit class construction when an implicit one is defined
1423    F# Compiler         bad error message: The member or object constructor 'Random' takes 1 arguments but is here supplied with 1.
1227    F# Compiler         ensure we can supply named and optional arguments to COM-interop methods
1404    F# Compiler         optional arguments handled incorrectly when using a method as a first class function value.
1418    F# Compiler         Methods on Enums should not be allowed
1457    F# Compiler         FParsec test 0.4.2. failing with byref check
1185    F# Compiler         change .[] overload resolution behaviour
1244    F# Compiler         unnecessarily choosing defaults for variables unconstrained, leading to spurious warnings and true errors being needlessly downgraded to warnings
1430    F# Compiler         Compiler spits out duplicate errors when given bogus syntax for named arguments
1462    F# Compiler         Poor (and repeated) error message on type mismatch
1034    F# Compiler         Downcasting for interface types
151     F# Compiler         Cannot construt delegate values that accept byref arguments
1024    F# Compiler         bug in type inference allows normal values to be polymorphic (type functions have to be declared explicitly and only at the top level)
1187    F# Compiler         problem with object constructors and self references
1476    F# Compiler         Setting static field in generic type fails to resolve in typechecker
1365    F# Compiler         unexpected Warning 65 in the absence of structural hashing and comparison
1472    F# Compiler         double quote breaks comment parsing (F# not fully compatible with OCaml)
338     F# Compiler         Incomplete pattern matches should report cases that are not covered.  THis could also be used by VS plugin when suggesting completions
1366    F# Compiler         Unboxing inconsistencies w.r.t 'null'
1488    F# Compiler         Implement redundancy checking for isinst patterns
1322    F# Compiler         Unhandled Exception using --clr-mscorlib option
1470    F# Compiler         Misleading warning "unit was constrained to FSharp.Core.Unit"
1484    F# Compiler         Internal Error when compiling a try-with construct
1342    F# Compiler         Bad error messages when constructs can't be quoted
1433    F# Compiler         Count of supplied parameters incorrect in error message if named parameters are used.
1060    F# Compiler         Quotation error: type varaible not found in environment
1463    F# Compiler         quotation of a private value error is not reported until codegen, so is not reported in Visual Studio
1445    F# Compiler         Failure when generating code for generic interface with generic method
1390    F# Compiler         Pattern matching with bigint literals does not work
1105    F# Compiler         params attributes not supported
1279    F# Compiler         Constructor call with the object-initialization-expr should error
1278    F# Compiler         Unresolved generic constructs in quotations should error instead of warn.
609     F# Compiler         not printing explicit type constraints on type declarations
1101    F# Compiler         spurious warning:This construct causes code to be less generic than indicated by the type annotations. The type variable 'd has been constrained to be type 'System.IDisposable'.
1502    F# Compiler         implement a "sealed" attribute
1533    F# Compiler         Support "static let"
1233    F# Compiler         cyclic inheritance bug
1452    F# Compiler         Complete checks for structs
1529    F# Compiler         Incorrect IL generated for call to static method on a valuetype
1490    F# Compiler         can't use typeof in attributes
997     F# Compiler         Unable to implement interfaces with generic methods
1570    F# Compiler         New testcase for "CustomAttributes on Module" failing
1392    F# Compiler         Space should not be required between : and >
1437    F# Compiler         Assembly attribute w/array parameter fails to build
1497    F# Compiler         Quotations 'bindCtor' issue (WebTools & F# 1.3.9.14)
1622    F# Compiler         Cannot use "null" in Attributes
1258    F# Compiler         Consider design for parser and typechecker that doesn't require exceptions
1050    F# Compiler         dot notation on datatype constructors is not resolved
1094    F# Compiler         implement internal/public access control escape checks
1160    F# Compiler         object should be evaluated eagerly when using a method as a first class function
1304    F# Compiler         Explicit program entry point
1500    F# Compiler         support conditional compilation (e.g. DEBUG, CODE_ANALYSIS)
1541    F# Compiler         finally clause in seq is called out of order, before yield
1590    F# Compiler         printf formats should reveal enough information to allow a reasonable implementation of using them in active patterns to scan strings
1644    F# Compiler         Generated .fsi is wrong for optional (?-style) parameters
791     F# Compiler         OverloadID attributes not in generated .fsi files
1552    F# Compiler         Internal error: badly formed Item_ctor_group.
1332    F# Compiler         ReflectedDefinition returning null should be allowed
1542    F# Compiler         Repeated type argument not being inferred: type Graph <'a> = HashMultiMap<'a,'a>
959     F# Compiler         TOp_asm in pattern match
1254    F# Compiler         Spurious casts being inserted for upcast operations
1379    F# Compiler         Property setter notation be used with mutable .NET fields and mutable record fields
1754    F# Compiler         Indexer access should use overloading and not warn on generic constraint
721     F# Compiler         suggested undentation from Robert pickering
1398    F# Compiler         indentation rule is too strict
1458    F# Compiler         Using anonymous type variable in attribute should either not be allowed or should do the right thing
1762    F# Compiler         Method name resolution should consult intrinsic methods first
1764    F# Compiler         Apply ADJACENT_PREFIX_MINUS rules to '+' as well.
1765    F# Compiler         members being printed in reverse alphabetical order in signatures
1766    F# Compiler         Treat all the funky operator names like '.[]<-' as single tokens.
1767    F# Compiler         Desugaring of computation expressions should make use of operator overloading
1768    F# Compiler         Allow the definition of immutable structs using the implicit construction syntax
1526    F# Compiler         Possible Regression in FSforScientists sample
1165    F# Compiler         Support return attributes?
1660    F# Compiler         testcase failure: fsharp\core\verify
1608    F# Compiler         Testcase failure: MutateStructFieldOnPropertySet
1112    F# Compiler         Bug in definition of generic interface
1625    F# Compiler         fsc generates assemblies that don't load/peverify
1683    F# Compiler         dispatch slot checking in object expression manages to match non-virtual member
1730    F# Compiler         F# allows Enums over string type (Does not PEVerify)
1743    F# Compiler         incorrect resolution of overrides
1748    F# Compiler         Internal Error: when calling a base member
1749    F# Compiler         Interfaces should not allow implicit construction pattern. Bad codegen.
1431    F# Compiler         'end' token ambiguity for interface/class: Incorrect and unactionable error messages when defining class which just implements an interface
1148    F# Compiler         class that only implements interface is parsed/recognised as interface (#light)
1275    F# Compiler         signature matching is comparing declared interfaces not interface sets
1553    F# Compiler         Checks associated with internal and private modules are not yet fully implemented.
1802    F# Compiler         Give error messages a "default" number to ensure consistent error message format
1803    F# Compiler         Field fails to hide property in parent
732     F# Compiler         private modules still appearing in VS object browser
1797    F# Compiler         large error range when solving constraint
942     F# Compiler         mutable variable escapes its scope when used with an event handler
1505    F# Compiler         Need to generate 'GetHashCode' on eception types
1707    F# Compiler         MaxInt+1 numeric literals should error
1530    F# Compiler         Attributes on properties should not also be put on getter and setter
1077    F# Compiler         closing brace following generic type bracket is syntax error without whitespace (lexed into symbolic token).
1831    F# Compiler         Finally block called twice for nested sequence comprehensions
1854    F# Compiler         TestCase Failure: Peverify error in Adcenter Adpredictor sample
1763    F# Compiler         Resolution to extension members should look through the entire hierarchy of a type
1363    F# Compiler         Need to apply DefaultMemberAttribute to enable C# to consume F# Indexers

313     F# Tools            fsyacc --ml-compatibility: Does not open the Parsing module

1425    F# Library          check structural equality on non-zero based multi-dimensional arrays
932     F# Library          Fix NaN equality on structured terms and make structural equality go through object.Equals
1059    F# Library          "=" doesn't work with 2D array values
1311    F# Library          NullReferenceException in StructuredFormat.Display.leafFormatter
1384    F# Library          Suggestion: allow explicit exception type definitions to override members - specifically the Message property
975     F# Library          Map Exceptions: when a key is not in a map, we get an index out of range exception instead of something like KeyNotFoundException
1572    F# Library          support "enum" and "delegate" type decomposition constraints for typesafe generic code over enums and delegates (e.g. conversions and event creation)
1591    F# Library          Bug in Async.Generate reported by David M Peixotto [dmp@rice.edu]
1598    F# Library          Problem with Array.fold1_left
1571    F# Library          Allow "int" and "char" functions to convert to/from int/char
1740    F# Library          problem with Lazy.SynchronizedForce()
1760    F# Library          Implement Unchecked.defaultof<_> (delete LanguagePrimitives.DefaultValueUnchecked)
1761    F# Library          Implement IComparable and Equals on Math.Complex
1374    F# Library          compelx number pretty printing broken
1776    F# Library          async implementation hits tail recursion problems on 64-bit
1796    F# Library          ThreadAbort is causing PostSync to raise exception
1800    F# Library          implement decimal literals, "decimal" conversion function
1801    F# Library          implement 'sign' and 'round' overloaded functions in library
1804    F# Library          sprintf "%A" formats should print decimal literals in "g" format rather than any specific floating point format
1731    F# Library          Need a way to cast primitive types to/from enums
1108    F# Library          Langauge Specifiation Issue: Enumerations don't convert to int32, uint32 etc.
1861    F# Library          lock function can be used on integers

1791    F# Perf         Apply fold_left performance improvements to research branch (for Morgan Stanley)

1819    F# Testing          Test error in tmptest.mli

1467    F# Language         AbstractClass attribute
1599    F# Language         Dispose not called in 'use _ = foo()'
1248    F# Language         symmetric overloading
339     F# Language         Support generic recursion
1558    F# Language         Should offside rule be applied to last clause of match?
1633    F# Language         Compiler override of Equals should not throw exceptions, per .NET coding guidelines.
1638    F# Language         When functions are use/passed as values, we should not insist on optional values.
755     F# Language         support marsahlling parameter and return attributes
1395    F# Language         parsing of minus (-)
641     F# Language         Deprecate (type ty) syntax
1614    F# Language         Should classes, unions, exceptions, records etc have a way to _not_ be marked with Serializable?

1535    F# Visual Studio    Tooltip for List.combine claims "List.combine is a synonym for List.combine"
1651    F# Visual Studio    Public constructors of non-visible types are showing up in top-level completion list
1652    F# Visual Studio    Namespaces with no visible members at a given program point should not be included in completion list

Changes between v1.9.2.9 and 1.9.3.14

Language Changes and Enhancements

This release includes a prototype of access controls, a feature that lets you use the keywords internal and private to mark values, members, record fields and union constructors with restricted visibility. For example:

    let internal x = 1
    type MyRecord = 
        { private x : int } 
        member obj.TwiceX = obj.x + obj.x
        static member Create(n) = { x = n }

CAVEAT: a number of checks are not yet implemented. In particular, if you mark a type or a module with private or internal you will get a warning that the checks for these kinds of constructs are not yet complete.

Type augmentations separated from a main type definition now give a warning if they contain interface implementations or implementations of overrides (see TypeAugmentations). This is because of the unsoundess mentioned as part of the specification, in particular "Augmentations that define interface implementations and override defaults may result in undefined behaviour if the intervening code creates instances of the object at runtime and makes calls via the virtual dispatch slots implemented by these functions (ill-defined recursion cycles can in principle occur)." This feature may be deprecated in a future release of the language.

The "static optimization" language construct now gives a warning it is used outside the implementation of the F# library. Use of this construct requires extreme care and if misused can cause unverifiable to be genreated or lead to the behaviour of code varying under different optimization settings.

F# now permits classes (including those with implicit constructors) to have uninitialized val fields marked with DefaultValueAttribute. This is primarily for codedom codegen. These fields will be initialized to null or the zero-bit-pattern for structs. These may also be marked static val. As a result we also implemented the setting of static F# fields.

Add EDITING define to Visual Studio mode: this is ON as far as Visual Studio editing is concerned, but OFF for compilation and execution. This is useful when mimicking generated codedom code in a partially implemented file

Constructed class types may now be mutually recursive with other types.

Multiple custom attributes can now be specified using repeated uses of [< ... >], as well as via the previous technique where a single [< ... >] is used with semicolon separation.

Ranges such as [ 1.1 ... 100.1 ] over floating point numbers are now deprecated. The floating point computations here are inherently highly sensitive and the resulting sequences often end up having a non-intuitive number of elements under any reasonable specification. For now use an integer range and convert to floating point. We expect to add a 'linspace' operator giving size and number of divisions in a future release.

Add prefix operators "%" and "%%" as ASCII-equivalent for Unicode section marker operator used for splicing into quoted expressions (i.e. for data binding into quotations expressions).

Library Changes and Enhancements

The F# libraries have been renamed: fslib.dll becomes FSharp.Core.dll and mllib.dll becomes FSharp.Compatibility.dll. This renaming has been planned for some time in order to give F# DLLs more standard .NET library names and we believe it will help us to grow the library further as time goes on.

Move some less important collections to FSharp.Compatibility.dll.

Move the Int32, Int64 etc. modules to FSharp.Compatibility.dll, though they currently remain in the Microsoft.FSharp.Core namespace.

Deprecate the undocumented Microsoft.FSharp.Core.Func module.

Some additional identifiers have now been marked with the 'OCaml compatibility' attribute

Added Permute to vector type, PermuteRows, PermuteColumns to matrix type.

Improved Library Documentation. Thanks to Ralf Herbrich for helping us complete minimal documentation for each funciton in the library.

Add Async.Parallel2 and Async.Parallel3 to Microsoft.FSharp.Control

Add more members to BigInt, Add modulus operator to BigInt.

Add INormFloat for generic distance algorithms.

Add WebRequest.GetResponseAsync to Microsoft.FSharp.Control.CommonExtensions.

Add delay to seq.countBy

Samples and Tools

FxCop: Fix some low hanging fruit so fewer errors are reported

Adjust ConcurrentLife sample so it compiles and runs correctly

Update F# Linq samples to match the Expert F# book and to work with Orcas Beta2

Improved ASP.NET sample help

Add command line option to permit the name of mscorlib.dll to be set. For use with Singularity.

Bugs Fixed

    1007 F# Compiler       Improve error message for property member without "this" (was internal compiler error).
    1061 F# Compiler       Two property nodes being generated for get/set metadata
    1103 F# Compiler       Bad code generation for active patterns from fswebtools example
    1104 F# Compiler       *** WARNING: basic block at end of method ends without a leave, branch, return or throw. Adding throw
    1111 F# Compiler       fswebtools code doesn't verify
    1112 F# Compiler       Cannot define an interface with a generic method
    1116 F# Compiler       Active pattern example fails where function is defined by matching (Reported by Andrew Kennedy - thanks Andrew!)
    1117 F# Compiler       Bindings that look like function definitions are interpreted as pattern 
                           matches without warning. Add a warning for this case to allow for later language 
                           design change here.
    1121 F# Compiler       Allow attribute targets "module", "type", "assembly", "class", "struct", "interface", "delegate", "property", "field"
    1126 F# Compiler       Unverifiable code generated by TLR and other optimizations when used with 
                           constrained local generic functions

    1253 F# Compiler       Implement optimizations related to 'when' filters in sequence expressions
    1255 F# Compiler       Make static optimization construct library-only (give a warning)
    1261 F# Compiler       CodeDom bug: FieldTest is failing in codedom suite
    1263 F# Compiler       Nested mutable structs not being mutated correctly 
    1264 F# Compiler       bignum/bigint literals don't meet specification, e.g. f -3N is accepted when it should be f (-3N) like all other integer forms
    1265 F# compiler       Deprecate #hardwhite and #white (old names for #light)
    1266 F# Compiler       Internal values are being optimized away in cross-module situations
    1271 F# Compiler       Internal and Private keywords in 1.9.33
    1272 F# Compiler       New-ing a sub class with unimplemented abstract members should not be allowed (reported by Keiko Nakata - thanks Keiko!)
    1300 F# Compiler       [FS 1.9.3.7] Issue with bindMethodBySearch & bindProp in quotations.fs
    1324 F# Compiler       [FS 1.9.3.7] Bad binary created when implementing COM interop interface. (Gacutil: Method does not have an implementation)
    1318 F# Compiler       [FS 1.9.3.7] Weird behavior instantiating .NET objects
    1317 F# Compiler       [FS 1.9.3.7] assembly private internal fields are leaking across assemblies through inline
    1238 F# Compiler       Bug reported by Tomas Petricek: give error when extension members defined in a namespace
    1336 F# Compiler       constraints "struct" and "not struct" do not work in #light code, and "not struct" never works

    972  F# Interactive    FSI reports "error: forceM: - envGetMethB: failed"
    982  F# Interactive    Visual Studio FSI doesn't function correctly on some machines. Force session to be in UTF8. 
                           This fixes a codepage related bug that rendered input/output invisible.
    984  F# Interactive    --exec doesn't function correctly
    1027 F# Interactive    Incorrect parsing of some expressions. Expr interactions were dropping lookahead tokens.
    1053 F# Interactive    Bug  accessing XLinq op_Explicit method from FSI
    1198 F# Interactive    #time ms printing 2d not 3d

    1033 F# Visual Studio  Some errors related to DLL references were being swallowed into Visual Studio (reported only once then swallowed into cache).
    1037 F# Visual Studio  Adjust "incomplete matches warning" so it underlines less intrusively in visual studio.
    1100 F# Visual Studio  Missing DLLs specified in project arguments not reported correctly in Visual Studio error window
    1106 F# Visual Studio  VS mode is swallowing some errors that reporting that a DLL can't be found
    1303 F# Visual Studio  F# addin global keybinding localisation work around - failing on KoreanOS/DefaultVS.

    1095 F# Samples        Ensure FLinq really works under Orcas Beta2
    1267 Samples           PersonalWebSite sample is busted (reported by Tomas Petricek)
    1268 Samples           F# version number not being added to web.config files in samples

    1118 F# Library        Scaling operator missing from matrix class (reported by Martin Szummer - thanks Martin!)
    1017 F# Library        Range comprehensions fixes for wraparounds and min/max int conditions. Exact number of steps with floats where possible.
    1051 F# Library        Calls to F# members should be quoted as MethodCall and PropertyCall nodes in the quotation tree
    1127 F# Library        foldByCol and foldByRow are incorrectly implemented in F# matrix library
    1129 F# Library        Add RowVector.zero to the F# matrix library
    1080 F# Library        Seq.cache_all does not have the properties of cache. Deprecate Seq.cache_all, 
                           add Seq.cache to return a IDisposable handle
    1215 F# Library        bigint now has properties which are printed by fsi.
    1293 F# Library        HTML docs hrefs to lower case types not always correct


    1052 F# Tools          Fix numerous issues with CodeDom code generation: Generate static fields, Remove old hacks 
                           for generating static fields, Generate type code snippets,Fix order of 
                           compilation of files.


Changes between v1.9.2.6 and 1.9.2.9

Changes

Changes between v1.9.1.17 and 1.9.2.6

Slicing syntax

The following syntax forms

    expr := ...
          | e1.[range1]
          | e1.[range1,range2]

    range := e2..e3
           | ..e3
           | e2..
           | *

represent slicing from a 1D or 2D data structures that supports associative lookup on ordered keys. In practice these forms can be used with

For example:

    let s1 = "abcdef"
    s1.[*] = s1
    s1.[0..] = s1
    s1.[1..] = "bcdef"
    s1.[2..] = "cdef"
    s1.[5..] = "f"
    s1.[6..] = ""

    let m1 = matrix [ [  1.0; 2.0; 3.0; 4.0; 5.0; 6.0 ];
                      [ 10.0;20.0;30.0;40.0;50.0;60.0 ]  ]
    m1.[*,*] = m1

    m1.[0..,*] = matrix [ [ 1.0; 2.0; 3.0; 4.0; 5.0; 6.0 ];
                          [ 10.0;20.0;30.0;40.0;50.0;60.0 ]  ]

    m1.[1..,*] = matrix [ [ 10.0;20.0;30.0;40.0;50.0;60.0 ]  ]

    m1.[*,1..] = matrix [ [  2.0; 3.0; 4.0; 5.0; 6.0 ];
                          [ 20.0;30.0;40.0;50.0;60.0 ]  ])

The primary restriction is that the syntax can't yet be used to extract a vector from a matrix, e.g.

    m1.[1,*]
    m1.[*,1]

are not yet valid syntactic forms. These would have to map to different operators.

Technically speaking, the above represent calls to the Microsoft.FSharp.Core.Operators operators

    val (.[..])     : ^src -> 'idx option -> 'idx option -> ^res    
    val (.[..,..])  : ^src -> 'idx1 option -> 'idx1 option -> 'idx2 option -> 'idx2 option -> ^res

i.e.

    e1.[e2..e3]   ==     (.[..]) e1 (Some e2) (Some e3)
    e1.[e2..]     ==     (.[..]) e1 (Some e2) None 
    e1.[..e3]     ==     (.[..]) e1 None      (Some e3) 

The implementation of (.[..]) requires:

Similar conditions are used for the 2D lookup operator.

Optional Arguments

Members (but not let-bound functions) may have optional arguments. These must come at the end of the argument list. An optional argument is marked with a ? before its name. Inside the member the argument has type option<argType>. On the callside the argument typically appears to have type argType, though there is a way to pass a value of type option<argType> if necessary (see below).

    let defaultArg x y = match x with None -> y | Some v -> v

    type T() = 
        static member OneNormalTwoOptional (arg1, ?arg2, ?arg3) = 
            let arg2 = defaultArg arg2 3
            let arg3 = defaultArg arg3 10
            arg1 + arg2 + arg3

        static member TwoOptional (?arg1, ?arg2) = 
            let arg1 = defaultArg arg1 3
            let arg2 = defaultArg arg2 10
            arg1 + arg2 

In a signature optional arguments appear as follows:

    static member OneNormalTwoOptional : arg1:int * ?arg2:int * ?arg3:int -> int
    static member TwoOptional : ?arg1:int * ?arg2:int -> int

Callers may specify optional arguments either:

For example:

    T.OneNormalTwoOptional(3)
    T.OneNormalTwoOptional(3,2)
    T.OneNormalTwoOptional(arg1=3)
    T.OneNormalTwoOptional(arg1=3,arg2=1)
    T.OneNormalTwoOptional(arg2=3,arg1=0)
    T.OneNormalTwoOptional(arg2=3,arg1=0,arg3=11)
    T.OneNormalTwoOptional(0,3,11)
    T.OneNormalTwoOptional(0,3,arg3=11)
    T.OneNormalTwoOptional(arg1=3,?arg2=Some(1))
    T.OneNormalTwoOptional(arg2=3,arg1=0,arg3=11)
    T.OneNormalTwoOptional(?arg2=Some(3),arg1=0,arg3=11)
    T.OneNormalTwoOptional(0,3,?arg3=Some(11))

Optional arguments can't be used in member constraints. They can be used in interface and abstract members. The compiled representation of optional arguments is fragile, in the sense that the addition of further optional arguments to a member signature will result in a compiled form that is not binary compatible with the previous compiled form.

Named Arguments

Calls to members (but not let-bound functions or function values) may use named arguments. For example

    System.Console.WriteLine(format="Hello {0}",arg0="World")
    System.Console.WriteLine("Hello {0}",arg0="World")
    System.Console.WriteLine(arg0="World",format="Hello {0}")

Named arguments may not be used with the curried arguments of a member (only the initial set of "tupled" arguments).

Named arguments must appear after all other arguments:

    System.Console.WriteLine(arg0="World","Hello {0}")

The names of members may be listed in signatures and on the signatures used for abstract members, e.g.

    static member ThreeArgs : arg1:int * arg2:int * arg3:int -> int

    abstract TwoArgs : arg1:int * arg2:int -> int

Hashing and equality on F# values

Recall that F# automatically implements comparison and hash semantics for tuple, record and discriminated union types (only). Now F# will also implement Object.GetHashCode and Object.Equals for these types. For example:

    > let x = box (1,2);;

    val x : obj

    > x.GetHashCode();;
    val it : int = 5
    > let x2 = box (1,2);;

    val x2 : obj

    > x2.GetHashCode();;
    val it : int = 5

    > x2.Equals(x);;
    val it : bool = true

This means System.Collections.Generic.Dictionary etc. will now be usable with tuple, record or discriminated union keys with the expected semantics without supplying a custom comparer. This eliminates a common source of confusing and possible unexpected behaviour.

Language enhancements

Library additions

Library minor changes

Bugs Fixed

Bugs fixed:

    977 Fix: resx files compiled without change to cwd.
        Fix: FSI reflection emit support for constrained callvirt opcodes.
        Fix: Hashtbl copying bug.
        Fix: nested module/type loading bug.
        Fix: performance improvements to BigNat and BigInt.

Changes between v1.1.9.8 and 1.9.1.17

Language Enhancements

New keyword. The identifier use is now a keyword.

use bindings for deterministic resources. In expressions the binding form use x = expr in body is equivalent to using expr (fun x -> body). Otherwise the binding form has the same behaviour as let, e.g. the in can be dropped when using the #light syntax option.

Reserve keywords for future syntax extensions. All identifiers ending with ! and ? are now reserved for future language extensions.

Reserve keywords for accessiblity extensions. The identifier internal is now reserved as a keyword.

Deprecate old defaulting scheme for overloaded operators.. Once upon a time all statically-resolved overloading operators used an implicit default of int. THis default can now be explicitly defined using a series of default constraints. The old scheme has been removed. This should result in better error messages in many situations.

Can now use flag1 ||| flag2 as constants in custom attributes. e.g.

      []

Library Enhancements

Experimental Asynchronous Computation Library. See Microsoft.FSharp.Experimental.Control.

Experimental Workflow/Monadic Syntax. See Microsoft.FSharp.Experimental.Control.

Bugs Fixed

Bugs fixed:

    951 11/05/2007      F# Visual Studio Plugin         Major intellisense failure
    830 11/05/2007      F# Visual Studio Plugin         Intellisense should show enum values in hover over or "dot" lookup on an enum typed-value
    926 11/05/2007      F# Compiler                     assertion failure in tc.ml
    531 11/05/2007      F# Language                     Cannot use "A ||| B" in enum flags when specifying a custom attribute (not a recognised constant)
    937 10/05/2007      F# Language                     enums on not int32 types? e.g. int64.
    948 04/05/2007      F# Compiler                     xml docs are getting dropped on properties
    946 02/05/2007      F# Compiler                     comment lexing does not handle quotes and backslashes inside verbatim strings
    945 02/05/2007      F# Compiler                     comment lexing does not handle quotes inside quoted strings 
    944 01/05/2007      F# Language                     Need to split IDelegateEvent into IPrimitiveDelegateEvent and IDelegateEvent (for CodeDom)
    936 01/05/2007      F# Compiler                     custom attributes with enum typed properties generate invalid IL code.
    934 01/05/2007      F# Compiler                     undescore and uppercase variables may not be used as arguments to object constructors
    935 01/05/2007      F# Compiler                     name clashes in generated field names (a/a0)
        17/05/2007      F# Compiler                     fix minor bugs preventing F# Interactive from running on Mono
        17/05/2007      F# Compiler                     fix bug with code generation for pattern matching on structs
        17/05/2007      F# Compiler                     make Microsoft.FSharp.Math.Complex a struct
        17/05/2007      F# Compiler                     Check virtual slots are revealed in signatures if the type is revealed to have an object-model representation
        17/05/2007      F# Compiler                     Fix two Visual Studio crashes due to recursive class hierarchies and recursive type abbreviations
        17/05/2007      F# Compiler                     Intellisense for F#-defined enum types
        17/05/2007      F# Compiler                     Fix bad error mark in Visual Studio for missing DLL reference
        17/05/2007      F# Compiler                     Fix long comment parsing
        17/05/2007      F# Compiler                     Fix install on Orcas Beta1
        17/05/2007      F# Compiler                     Fix minor problem with DLinq sample
        17/05/2007      F# Compiler                     Minor fixes for Microsoft.FSharp.Experimental.Control.Async
        17/05/2007      F# Compiler                     Allow access to the types implicity defined by 'exception' declarations
        17/05/2007      F# Visual Studio Plugin         Auto install for VS versions 7.1, 8.0 and 9.0 (Orcas Beta 1)

Changes between v1.1.9.8 and 1.9.1.9

Library Enhancements

Overloaded numeric conversion functions. The functions int, float, float32 etc. now overloaded conversion operators. For example, you can replace Int32.of_float and Int32.of_int64 and all similar operators that convert to int by just int (or int32, which is equivalent). Likewise for sbyte, byte, int16, uint16 int32, uint32, int64, uint64, nativeint, unativeint, float, float32, single, double.

Checked arithmetic Open Microsoft.FSharp.Core.Operators.Checked to get checked arithmetic versions of +, -, * and the above conversion operators.

Updated FLinq sample The FLinq sample has been updated to use the technique outline in Don Syme's ML Workshop LINQ paper from 2006. More details to follow in blog entries.

Bugs fixed:

    895         "type" links broken on F# manual pages online
    893         unicode lex bug 0x800 - 0x7ff
    894         file hashes not being added to assembly resouce 
    900         --quotation-data flag problems causing problems for many things in F# Interative from Visual Studio
    903         catch and report exceptions on user threads without killing fsi
    907         quotation API TopDefnData should use an Assembly value.
    909         Add Seq.cache_all
    910         Seq.filter is broken on 64-bit
    911         Fast F# cannot be unset, and should be ignored anyway
    898         Invislbe error location information reported in Visual Studio
    912         {} still gives tyref_of_stripped_typ
    914         Pattern matching code causes NullReferenceException
    913         Nested enums not showing up under intellisense, e.g. System.Environment.SpecialFolder
    904         explicit instantiation of generic type not found
    905         Intellisense failure for static method in generic collection class
    918         Poor error when generic type given the wrong number of type arguments
    916         Should not be printing to stderr on "fsi --exec"
    915 Add updated LINQ sample (updates are on Don’s laptop)
    924 structural comparison should fail for incomparable types
    923 Add Array2.rebase
    922 Use operator overloading for colelction types Tagged.Set, Tagged.Map, Tagged.HashSet, Tagged.HashMultiMap

Changes between v1.1.13.8 and 1.9.1.8

Language Enhancement: Implicit Class Construction

This release includes a preview version of ``implicit class construction'' or the ``compact class syntax''. An class has an implicit constructor if arguments are present following its type declaration. The arguments to the implicit constructor follow the type name, then a sequence of let-bindings (prior to the members) define the object initialisation. Note, the let bindings are in scope over the members, but they are private to this class. For example:

    type File1(path) = class
        let innerFile = new FileInfo(path)
        member x.InnerFile = innerFile
    end
    let myFile1 = new File1("file.txt")

Classes with an implicit constructor have zero, one or more arguments such as path after the name of the type constructor. Furthermore the body of the class may contain let bindings, which are always private to the class, indeed private to the object (you can't access the let bindings even for other values of the same type). Above we have also added the a property member InnerFile to reveal the value of the value of the innerFile. Here is a second example:

    type Counter(start, increment, length) = class 
        let finish = start + length
        let mutable current = start
        member obj.Current = current
        member obj.Increment() = 
            if current > finish then failwith "finished!";
            current <- current + increment
    end

Logically speaking, this class is equivalent to:

    // The above code is equivalent to the following:
    type Counter = class 
        val start: int
        val increment: int
        val length : int
        val finish : int
        val mutable current : int
        new(start, increment, length) = 
            { start=start;
              increment=increment;
              length=length;
              finish = start + length; 
              current = start; }
        member obj.Current = current
        member obj.Increment() = 
            if obj.current > obj.finish then failwith "finished!";
              obj.current <- obj.current + obj.increme
    end

The first definition of Counter is one third the size of the second, so obviously the syntax has some advantages. Indeed we believe this feature is part of the key to enabling mixed OO/functional programming in practice.

Note this feature is in many ways similar to those found in OCaml and other langauges.

Classes can include both implicit and explicit constructors

When using implicit class construction the call to the base class constructor is specified as part of the inherits declaration itself.

    type Base1(state:int) = class
        member x.State = state
    end
                   
    type Sub1(state:int) = class
        inherit Base1(state)
        member x.OtherState = state
    end
    
    let myOtherObject = new Sub1(1)

The types may be generic. Type annotations are generally required:

    type Base1<'a>(state:'a) = class
        member x.State = state
    end
                   
    let myObject1 = new Base1<int>(1)
    let myObject2 = new Base1<string>("1")

Known Limitation: The F# compiler is free to optimize and represent the let-bindings in anyway it deems fit. However, in this release each ``let'' binding gives rise to a field in the class. This is the main reason why we say this feature is only a ``tech-preview'' - while it is extremely useful even as it stands you have to be a little careful not to put thousands of helper (e.g. closed-form) ``let'' bindings in a critical class. In the above example, the start value is only required during initialization of the object and thus should in principle not be included as a field of the object.

Known Limitation: In this release classes with implicit constructors may not be mutually recursive.

Known Limitation: Patterns may not be used in the arguments to the constructor.

Known Limitation: The bindings are established in order. However base class constructors written in other .NET languages can in principal call virtual members prior to the complete initialization of the object. This means you should be careful about using your ``let'' bindings from override members that may be activated by base classes during base initialization. In this case the behaviour is unspecified and the 'default' or 'zero' values of some of the let bound variables may be observed.

Language Enhancement: Active Patterns

Active patterns give a form of extensible pattern matching on abstract values. F# active patterns allow you to pattern match against .NET object values such as XML, System.Type values and LINQ Expression trees. They allow a function to give a complete decomposition of an abstract type by projecting it into a union type.

Active Decomposition. An active pattern discrimination function declares a ``view'' on a type. It is a function whose name includes surrounding (| ... |) marks. It gives a technique for automatically decomposing the values of a type when the enclosed label(s) are used as pattern discriminator(s). For example:

   open Microsoft.FSharp.Math
   let (|Rect|) (x:complex) = Rect(x.RealPart, x.ImaginaryPart)
   let (|Polar|) (x:complex) = Polar(x.Magnitude , x.Phase)

These functions declare two unrelated discriminators for viewing the (abstract) type of complex numbers as tuples in rectangular and polar coordinates. Multiplication can now be expressed using either coordinate system:

   let mulViaRect c1 c2 = 
       match c1,c2 with 
       | Rect(ar,ai), Rect(br,bi) -> Complex.mkRect(ar*br - ai*bi, ai*br + bi*ar)
  
   let mulViaPolar c1 c2 = 
       match c1,c2 with 
       | Polar(r1,th1),Polar(r2,th2) -> Complex.mkPolar(r1*r2, th1+th2)

In the first case, the decomposition function (|Rect|) is run when the inputs c1 and c2 are matched.

Because Rect and Polar are simply pattern discriminators they can be used in any position where an existing pattern discriminator can be used:

      let mul2 (Polar(r1,th1)) (Polar(r2,th2)) = Complex.mkPolar(r1*r2, th1+th2)
  
      for (Polar(r,th)) in myComplexNumberList do 
          printf "r = %O, th = %O" r th

Active Discrimination. Active pattern discrimination functions may include multiple active pattern labels. For example, the following defines a function (|Named|Array|ByRef|Ptr|Param|) that discriminates and decomposes System.Type values into one of the five indicated cases:

      open System
      
      let (|Named|Array|ByRef|Ptr|Param|) (typ : System.Type) =
          if typ.IsGenericType        then Named(typ.GetGenericTypeDefinition(), typ.GetGenericArguments())
          elif not typ.HasElementType then Named(typ, [| |])
          elif typ.IsArray            then Array(typ.GetElementType(), typ.GetArrayRank())
          elif typ.IsByRef            then ByRef(typ.GetElementType())
          elif typ.IsPointer          then Ptr(typ.GetElementType())
          elif typ.IsGenericParameter then Param(typ.GenericParameterPosition, typ.GetGenericParameterConstraints())
          else failwith "unexpected System.Type"

You can now use these discrimination labels in pattern matching:

      let rec toString typ =
          match typ with
          | Named (con, args) -> "(" + con.Name + " " + String.Join(";",Array.map toString args) + ")"
          | Array (arg, rank) -> "(Array"  + rank.ToString() + " " + toString arg + ")"
          | ByRef arg         -> "(ByRef " + toString arg + ")"
          | Ptr arg           -> "(Ptr "   + toString arg + ")"
          | Param(pos,cxs)    -> "(Param " + any_to_string (pos,cxs) + ")"

This is by no means the only view that could be applied to this type, but it is a useful one when performing operations that are sensitive to the presence of type variables (Param) and generic type constructors (Named).

Active Patterns in the F# Library The F# library currently only includes active patterns for a few constructs. One is the LazyList type, a cached, lazily-computed list. This allows you to pattern match on LazyList values, including nested patterns, e.g. the following code performs pairwise summation on a lazy list:

    open LazyList
    
    let rec pairReduce xs =
      match xs with
        | Cons (x, Cons (y,ys)) -> LazyList.consf (x+y) (fun () -> pairReduce ys)
        | Cons (x, Nil ())      -> LazyList.cons x (LazyList.empty ())
        | Nil ()                -> LazyList.empty ()

Partial Active Patterns. Partial patterns are signified by adding a |_| to the name of the discrimination function. The body of the discrimination function must return a value of type 'option'. They are most useful when dealing with repeatedly recurring queries on very "heterogeneous" data sets, i.e. data sets able to represent a large range of possible entities, but where you're often interested in focusing on a subset of the entities involved. Strings, term structures and XML are common examples. Here is an example when matching on integers:

     let (|MulThree|_|) inp = 
        if inp % 3 = 0 then Some(inp/3) else None
     let (|MulSeven|_|) inp = 
        if inp % 7 = 0 then Some(inp/7) else None
  
     let example1 inp = 
         match 21 with 
         | MulThree(residue) -> printf "residue = %d!\n" residue
         | MulSeven(residue) -> printf "residue = %d!\n" residue
         | _ -> printf "no match!\n"
  
     example1 777
     example1 9
     example1 10
     example1 21

Partial patterns are by their nature incomplete and thus the benefits of completeness checking in pattern matching are almost completely lost when using these patterns.

Parameterized Active Patterns. So far all the pattern discrimination functions have taken one argument, i.e. the input being discriminated. Pattern discrimination functions may also take additional arguments that represent parameters to the pattern:

     let (|Equal|_|) x y = 
        printf "x = %d!\n" x
        if x = y then Some() else None

When used in a pattern a parameterized pattern tag may be followed by simple expressions that represent arguments, and then finally followed by the pattern being matched against, e.g.:

        
     let example1 = 
         match 3 with 
         | Equal 4 () -> printf "3 = 4!\n"
         | Equal 3 () -> printf "3 = 3!\n"
         | _ -> printf "3 = ?!\n"

Note: not all expressions can be used in this position. Only identifiers, tuples, applications, lists and array expressions may be written in this position. Here is a second example. Extra parentheses can be useful to distinguish pattern parameters from the variables being bound by the pattern:

     let (|Lookup|_|) x map = Map.tryfind x map
        
     let example2 = 
         match Map.of_list [ "2", "Two" ; "3", "Three" ] with 
         | Lookup("4")(v) -> printf "4 should not be present!\n"
         | Lookup("3")(v) -> printf "map(3) = %s\n" v
         | Lookup("2")(v) -> printf "this should not be reached\n"
         | _ -> printf "3 = ?!\n"

Values with the names of the form (| ... |) can in theory all be used as parameters, e.g.

    let mapQ1 f (|P|_|) = function (P x) -> Some (f x) | _ -> None

However this is not a common technique. Our final example shows the use of a simple set of active patterns to match on the concrete structure of an XML document and extract a recursive algebra from the document:

    open System.Xml
    open System.Collections
    open System.Collections.Generic
  
    let Select (|P|_|) (x: #XmlNode) = [ for P y as n in x.ChildNodes -> y ]
  
    let Select2 (|A|B|) (x: #XmlNode) = [ for (A y | B y) as n in x.ChildNodes -> y ]
  
    let (|Elem|_|) name (inp: #XmlNode) = 
        if inp.Name = name then Some(inp) 
        else None
  
    let (|Attr|_|) attr (inp: #XmlNode) = 
        match inp.Attributes.GetNamedItem(attr) with
        | null -> None
        | node -> Some(node.Value)
  
    let (|Num|_|) attr inp = 
        match inp with 
        | Attr attr v -> Some (Float.of_string v) 
        | _           -> None
  
    type scene = 
        | Sphere of float * float * float * float
        | Intersect of scene list 
    
    let (|Vector|_|) = function (Num "x" x & Num "y" y & Num "z" z) -> Some(x,y,z) | _ -> None
    
    let rec (|ShapeElem|_|) inp = 
        match inp with 
        | Elem "Sphere" (Num "r" r  & Num "x" x & Num "y" y & Num "z" z) -> Some (Sphere (r,x,y,z)) 
        | Elem "Intersect" (ShapeElems(objs)) -> Some (Intersect objs) 
        | _ -> None
  
    and (|ShapeElems|) inp = Select (|ShapeElem|_|) inp 
  
    let parse inp = 
        match (inp :> XmlNode) with 
        | Elem "Scene" (ShapeElems elems) -> elems
        | _                               -> failwith "not a scene graph"
  
    let inp = "<Scene>
                  <Intersect>
                    <Sphere r='2' x='1' y='0' z='0'/>
                    <Intersect>
                      <Sphere r='2' x='4' y='0' z='0'/>
                      <Sphere r='2' x='-3' y='0' z='0'/>
                    </Intersect>
                    <Sphere r='2' x='-2' y='1' z='0'/>
                  </Intersect>
               </Scene>"
    let doc = new XmlDocument()
    doc.LoadXml(inp)
    //print_endline doc.DocumentElement.Name
    printf "results = %A\n" (parse doc.DocumentElement)

Signatures for Active Patterns The signature for an active discrimination function is given in terms of a function returning a Choice type:

    val (|Cons|Nil|) : 'a llist -> Choice<('a * 'a llist),unit>

Notes: Some obvious issues with using active patterns in languages with side effects - how many times are discrimination functions executed? The specification used for F# is that "if pattern matching requires that an active discrimination function be run on a given input, then the pattern matching apparatus is free to run that function on the same input as many times as it wishes". In the presence of active patterns, rules of patterns are searched exhaustively on a left-to-right, top-to-bottom basis. We have chosen this semantics partly because we want to strongly discourage discriminator functions with side effects, in much the same way that side effects are strongly discouraged in code that implements the C# and F# property notations.

Known Limitation: Individual active pattern discrimination functions may decompose using at most 7 labels. Multiple partial active patterns can be used instead. It is planned that this limitation will be lifted in the next release.

Known Limitation: Choice types of size greater than 7 are not implemented in this release.

Much of this work was done by Gregory Neverov in the summer of 2006.

Language Enhancement: Methods as first-class values

Methods can now be used as first class values without eta-expansion. Context-sensitive type information is used to resolve overloading. For example:

    open System.IO
    let data1 = List.map File.ReadAllLines ["a.txt"; "b.txt"]

If applied to arguments methods must still be applied to a syntactic tuple of arguments where the number of elements in the tuple is the same as the numebr of arguments expected by the method.

Language Enhancement: Nested types may now be written C<D<int>>

This long-standing problem has now been fixed. This only applies if the type arguments follow immediately after a leading constructor without spaces, e.g. C<D<int>> not C <D <int>>.

Language Enhancement: Precedence of type annotations in pattern tuples

Until now, F# followed OCaml and give "comma" in parenthesized tupled patterns higher precedence than type constraints. This has changed. Thus we would previously disallow

     let f (samplefreq:int64, s:int64) 

and previously parse

     let f (samplefreq, s : int64) 

as

     let f ((samplefreq, s) : int64) 

(leading to a type error). We are changing this behaviour for parenthesized patterns, and now

     let f (samplefreq:int64, s:int64) 

will be accepted and parsed in the same way as

     let f ((samplefreq:int64), (s:int64)) 

and the following current code will almost certainly give an error

     let f (samplefreq, s:int64*int64) 

since it is now parsed as

     let f (samplefreq, (s:int64*int64)) 

Technically speaking this is a breaking change, though we have encountered only one example of user code affected by this. The readability of the user code was massively improved after taking the above change into account, hence in the balance we have decided the improvement to the language is more important in the long term. In all cases there are still reasonable and simple ways to ensure your code cross compiles with OCaml if necessary.

Other Language Enhancements

StructLayout, FieldOffset etc. attributes now supported for C interoperability.

F# Lists support IEnumerable/seq. In previous versions the F# list type was not compatible with the .NET IEnumerable<'a> type, which is called seq<'a> in F#. This was because null was used as a representation for lists. This has now been changed. See further discussion below.

Normalization of class and interface constraints. When constraints are used extensively situations can arise where a single type parameter can be constrained by multiple related constraints. For example,

   let f1 (x : #seq<('a * 'b)>) = ()
   let f2 (x : #seq<('a * 'b * 'c)>) = ()
   let g x = f1 x; f2 x

Here g is constrained to operate over both sequences of pairs and sequences of triples. While it is in principle possible for a .NET type to implement both of these interfaces, in practice this is never used. In prior versions F# was not normalizing such constraints to ensure that any particular nominal type occurred at only one instantiation for a given collection of constraints. This has now been added to the language specification and has been implemented. This gives earlier detection of errors involving incompatible constraints and ensures that multiple related constraints never need to be listed in signatures should one constraint subsume another.

Lexer literals 32u and 32uL now accepted. These are unsigned 32-bit and 64-bit integers.

new now optional. The construct new Type(args) can now optionally be replaced by simply Type(args). This applies when no ambiguity exists as to which type is being constructed and where no type instantiation is given. However, a warning is given if the type supports the IDisposable interface. For these constructs it is felt that the potential use of resources by the construct means that new Type(args) is much clearer

More F# keywords accepted as identifiers in --ml-compatibility-mode.

Enum values now support the ||| and &&& operators. This applies when the Enum type is marked with the FlagsAttribute attribute.

Extend overload inference for (+), (*) etc. to allow return types to propagate to the overload resolution. This reduces the need for type annotations in many circumstances.

Explicit type applications at member calls and path lookups. You can now explicitly apply type arguments in lookups, e.g.

    let x = Map.empty<string,int>
    // The next is from the Microsoft Research 'Joins' library
    let subscribe = Asynchronous.CreateChannel<EventSink<'b>>(client.Join)

Flexible printf integer and floating point format enhancements. %d, %u, %i, %x and %o formats can now be used with any integer types. Many of the other format specifiers have now been deprecated or marked 'for OCaml compatibility'. %f and %g and other floating point specifiers can now be used with both Single and Double precision numbers. The use of the format specifiers is still checked at compile time to ensure static type correctness.

Printf format enhancements. * can now be used as a width and/or precision specifier. This corresponds to a 'computed' specifier and an extra integer argument giving the width is required in the argument list for the specifier. For example:

     sprintf "|%*s|%*s|" 10 "hello" 8 "world" ;;
     sprintf "|%*s|%*s|" 12 "hello" 6 "world" ;;
  

Give:

    val it : string = "|     hello|   world|"
    val it : string = "|       hello| world|"

OCaml Compatibility Warnings. Several constructs in the F# libraries are only present for OCaml compatibility. While OCaml compatibility is a key goal of the language, we have also become aware that users coming to F# from a non-OCaml background get very confused by the presence of 'multiple ways of doing things' and are bemused when the explanation is that 'we need that for OCaml compatibility, but we don't really recommend using it'. As such, we've begun marking some constructs as 'not recommended for use unless you need it for OCaml compativility.' In this relesae this applies to &

Null no longer used as a representation for F# list values. We made this change to allow the F# "List" type to implement the IEnumerable/seq interface. This means we are dropping null as a representation for F# list values (null values cannot implement interfaces), and are indeed abandoning the use of "null" for option values and where an attribute is explicitly attached to a discriminated union with a nullary discriminator, e.g.

    [<CompilationRepresentation(CompilationRepresentationFlags.PermitNull)>]
    type HashChain<'a,'b> = 
      | EmptyChain // note: representation is "null"
      | Chain of { Key: 'a; 
                   Value: 'b; 
                   mutable Rest: ('a,'b) HashChain }

This is thus a breaking change to the language spec, which previously specified different conditions where "null" is used. Using non-null values for the empty list comes with a small performance penalty for list-intensive code (around 10%), but little overall space penalty. Array, loop, matrix, vector, hashtable, set, sequence and map-dominated code is not affected, and since these are the primary high-performance data structures in F# we have decided that the language clarity of having "list" implement "IEnumerable" is more important than the performance considerations for this case.

This change does mean that C# samples that search for "null" as the empty list will no longer function correctly. They should instead use the IsNil property (now a true instance property) or switch on tags, e.g. as follows:

       List<int> x = List>int>.Cons(3, (List<int>.Nil));

       switch (x.Tag)
       {
           case List<int>.tag_Cons:
               Console.WriteLine("Cons({0},{1})", x.Head, x.Tail);
               break;
           case List<int>.tag_Nil:
               Console.WriteLine("[]");
               break;
       }

Library Enhancements

Representation of the LazyList type is now private. Active patterns can now be used to match on values of type LazyList.

Sparse matrix implementation. See Math.Matrix.init_sparse. You can now create and multiply matrices up to size ~10M x 10M, as long as most elements are zero.

Updated quotations API. The quotations API has been substantially simplified through the use of active patterns. Code using the old quotations API directly will no longer compile but is easy to update. Contact the F# team if you need help you with this.

The F# map type now supports equality and comparison over entire map values. In particular Map<k,v> implements IDictionary<'k,'v>, IEnumerable<KeyValuePair<k,v>> and IComparable. Note: this is a breaking change. In 1.1.13.8 Map supported IEnumerable<'k,'v>. However, this meant that the type could never also support IDictionary. We have decided to make this breeaking change immediately since it is obviously correct for Map values to support IDictionary.

Interactive pretty-printer for IDictionary values.

Pervasive values cleaned up. Many values that are now "officially" part of Microsoft.FSharp.Core.Operators were still being redefined in Microsoft.FSharp.Compatibility.OCaml.Pervasives. These have now been removed from that module. The path Microsoft.FSharp.Compatibility.OCaml.Pervasives is still opened be default but contains very few values.

Overloading of math operations like sin, cos, abs etc. These are now overloaded over basic types, e.g. abs on all floating point and signed types, and sin on the floating point types. They also work with any type supporting corresponding static members, e.g. types supporting the static member Sin or Abs.

Choice types.

Choice types up to size 7 are defined in the F# library and can be used for general purpose programming.

    type Choice<'a,'b> = 
      | Choice2_1 of 'a 
      | Choice2_2 of 'b
    
    type Choice<'a,'b,'c> = 
      | Choice3_1 of 'a 
      | Choice3_2 of 'b
      | Choice3_3 of 'c

etc.

F# Reflection library additions to pre-compute faster accessors. The following functions have been added to thee reflection library:

    /// Precompute a function for reading a particular field from a record.
    val GetRecordFieldReader     : Type * field:string -> (obj -> obj)

    /// Precompute a function for reading all the fields from a record.
    val GetRecordReader          : Type -> (obj -> obj array)
    
    /// Precompute a function for reading an integer representing the discriminant tag of a sum type.
    val GetSumTagReader          : Type -> (obj -> int)

    /// Precompute a function for reading all the fields for a particular discriminant tag of a sum type
    val GetSumRecordReader       : Type * int -> (obj -> obj array)
    
    /// Precompute a function for reading the values of a particular tuple type
    val GetTupleReader           : Type -> (obj -> obj array)

    /// Precompute a function for constructing a record value. 
    val GetRecordConstructor     : Type -> (obj array -> obj)
    
    /// Precompute a function for constructing a discriminated union value for a particular tag. 
    val GetSumConstructor        : Type * tag:int -> (obj array -> obj)
    
    /// Precompute a function for reading the values of a particular tuple type
    val GetTupleConstructor      : Type -> (obj array -> obj)

    /// Precompute a pair of functions for converting between integer discriminant tags
    /// the names of the discriminants for the given sum type. The number of tags is also
    /// returned.
    val GetSumTagConverters      : Type -> int * (int -> string) *  (string -> int)

F# Reflection library no longer reports F# class types as records. This was a mistake from the early implementation of the reflection library.

Deprecated llist functions. Deprecated some LazyList functions.

LexBuffer.AsNewLinePos() renamed to LexBuffer.NextLine. The old name has been deprecated.

List.concat now accepts a sequence. This brings it into line with Seq.concat.

Notation for complex/matrix/vector/set/dict notation at the top level The following functions are now defined in Microsoft.FSharp.Core.Pervasives and are available for use in the top level:

    val complex : float -> float -> complex
    val matrix : #seq< #seq<float> > -> matrix
    val vector : #seq<float> -> vector
    val rowvec : #seq<float> -> rowvec
    val set : #seq<'a> -> Set<'a>
    val dict : #seq<'a * 'b> -> System.Collections.Generic.IDictionary <'a,'b>

Visual Studio Enhancements

Intelisense on more expressions, including method calls.

Visual Studio ToolsOptionsPage for FSI startup arguments

Visual Studio fixes to allow "ReadLine" calls when using VFSI

Minor bug fixes.


   Bug fixes to permit printf on binary channels (Reported by Richard Mortier - thanks Mort!)

   Fixed mod_float to be ocaml compatible (reported by Andrew Phillips - thanks Andrew!)

   Bug 858: Function types not erased from type constraints on typars of methods or types.
   
   Bug 856: no more inlining of protected calls, e.g. out of class defn.
   
   Bug 851. Removed ``0 from non-generic member names in xmldoc.

   Fix base calls to F# abstract members (reported by Ralf Herbrich and Phil Trelford - thanks guys!)
   
   XMLDOC changes (suggested by Andyman - thanks Andy)
 
   Permit access to nested generic classes (reported by Claudio Russo - thanks Claudio!)
 
   Fixed generation of unverifiable code when using the "property bag" syntax with properties 
   of type 'object' and values that are value types, a bug reported by Julien Ortin 
 
   Bug 880: Type definition bug (reported by Laurent on hubfs - thanks Laurent!)

   Bug 881: fsi needs a way to specify command line arguments (reported by Dmitry - thanks Dmitry!)

   Bug 882: StartupCode and PrivateImplemntationDetails types should be private (reported by Robert Pickering - thanks Robert!)

   Bug 883: Add check for phantom and permuting type abbreviations causing potential problems in type inference

   Bug 884: Instrumented profiling doesn't work on XP or Vista
   
   Bug 889: Excessive 'base' variable usage checks (reported by Tomas Petricek - thanks Tomas!)

Changes between v1.1.12.7 and 1.1.13.8

Language Enhancements

Range Comprehensions. e.g. {1 .. 3} and {0 .. 2 .. 10}. The both are IEnumerable<int>, generating [1;2;3] and [0;2;4;6;8;10] respectively, though the operator is overloaded and can be used with other types such as characters, bigint etc. Uses of this syntax correspond to overloaded oeprators (..) and (.. ..) respectively.

IEnumerable, Array and List Comprehensions.

It's been a long time in coming, but yes, finally a version of ML with comprehension syntax built-in right into the language. But what are comprehensions? We all know that aggregate operators are a very powerful way of working with lists, maps, sets and IEnumerable values. However, an even more convenient syntax is also provided for specifying the class of IEnumerable values that can be built using operations such as choose, map, filter, concat. This syntax is compiled down to the use of the aggregate operators above and is called the comprehension syntax. It can also be used to specify the shapes of lists and arrays.

Comprehensions using for

The simplest form of a comprehension is { for ... in ... -> result }, where -> should be read as 'yield'. This is simply a shorthand way of writing IEnumerable.map. As with range comprehensions the parentheses are not optional when using this syntax to generate IEnumerable values. For example, we can generated an enumeration of numbers and their squares as follows:

    > let squares = { for i in 0 .. 10 -> i,i*i} ;;
    val squares : IEnumerable<int * int> = [ (0,0); (1,1); (2,4); (3,9); ... ]

The more complete form of this construct is (for pattern in enumerable -> expression). The pattern allows us to decompose the values yielded by the input enumerable. For example, if the enumerable yields tuples we can decompose it as follows:

    > let cubes = { for i,isquared in squares -> i,isquared,i*isquared };;

    val range : IEnumerable<int> = [ (0,0,0); (1,1,1); (2,4,8); (3,9,27); ... ]

The input enumerable may be a list value, any IEnumerable, or a value of any type supporting a GetEnumerator method (some important types from the .NET libraries support this method without directly supporting the IEnumerable construct). Below is an example where the input is a list of options. If the pattern fails to match the element of the enumerable is skipped and no result is yielded.

    > { for Some(nm) in [ Some("James"); None; Some("John") ] -> nm.Length };;

    val it : IEnumerable<int> = [ 5; 4 ]  

An enumerable comprehension always begins with for … in …, but additional clauses can also be given, each of which may be one of:

Secondary iterations iterate in two dimensions. For example, the following function returns all the (row,column) pairs of the lower left triangle of a square matrix, including the diagonal:

    let lowerTriangleCoordinates n = 
      { for row in 0 .. n
        for col in 0 .. row
        -> (row,col) }

Filters allow us to skip elements, e.g. the following computes the coordinates of a matrix where the sum is even (i.e. a checkerboard):

    let checkerboardCoordinates n = 
      { for row in 0 .. n
        for col in 0 .. n
        when row+col % 2 = 0
        -> (row,col) }

Let and match clauses in comprehensions allow us to compute intermediary results and filter results through failing matches. For example, the following code gets the creation time and last access time for each file in a directory.


    let fileInfo dir =
       { for file in Directory.GetFiles(dir) 
         let creationTime = File.GetCreationTime(file) 
         let lastAccessTime = File.GetLastAccessTime(file) 
         -> (file,creationTime,lastAccessTime) }

The final yield of a comprehension may be another IEnumerable, signified through the use of the ->> symbol as the yield. The following sample shows how to redefine the allFiles function from the previous section using comprehension syntax.

    let rec allFiles dir =      
        IEnumerable.append
          (for file in Directory.GetFiles(dir) -> file)
          (for subdir in Directory.GetDirectories subdir ->> allFiles subdir)

Using Comprehension Syntax to Specify Lists and Arrays The comprehension syntax for ranges and generated enumerables can also be used to build list and array values. The syntax is identical except the surrounding parentheses are replaced by the usual [ ] for lists and [| |] for arrays. We discuss arrays in more detail in Chapter 3.

    > let squaresList = [ for i in 0 .. 3 -> i,i*i ];;

    val squaresList : (int * int) list = [ (0,0); (1,1); (2,4); (3,9) ]

    > let squaresArray = [| for i in 0 .. 3 -> i,i*i |];;

    val squaresArray : (int * int) list = [ (0,0); (1,1); (2,4); (3,9) ]

Named arguments and Property-setters-masquerading-as-named-arguments

.

Named items in object-model member calls are arguments of the form id=expr. Named items have been used for some time in the attribute syntax. These are now given two meanings in constructor calls and regular member calls:

    new MenuItem(text="Hello")  -- this is a named argument
    new Form(Width=300)         -- this looks like a named argument, and feels like one, but 
                                -- is actually a "property set" performed after the object has been constructed.

We've been planning this feature for a while, and it is also very close to the C# 3.0 syntax for property setters. Example:

    open System
    open System.IO
    open System.Text
    open System.Drawing
    open System.Windows.Forms
    
    let clickMenuItem = new MenuItem(text = "hello",onClick=new EventHandler(fun _ evArgs -> printf "click!\n"))
    
    let clickMenuItem2 = new MenuItem(text = "hello",onClick=(fun _ evArgs -> printf "click!\n"))
    
    let rec recursiveClickMenuItem = new MenuItem(text = "hello",onClick=(fun _ evArgs -> printf "self disabling\n"; recursiveClickMenuItem.Enabled <- false))
    
    let form = new Form(Width=500, Height=420,Visible=true,TopMost=true,
                        FormBorderStyle=FormBorderStyle.FixedSingle,
                        Text="99 bottles of beer presented in F#" )
    
    let rb = new RichTextBox(Size=new Size(480, 350),
                             Location=new Point(5, 5))
    
        form.Controls.Add(rb)
    
    let btnClose = new Button(Location=new Point(408, 360),Text = "Close")
    btnClose.Click.Add (fun _ -> f4.Close())
    f4.Controls.Add(btnClose)

Named arguments cannot be used with let-bound functions.

Fast 'for' loops for Range Comprehensions. Constructs of the form for i in n .. m do ... done have been optimized to ensure they also result in for-loops that are compiled and execute as efficiently as the 'simple' integer for-loops for i = n to m do ... done

Custom Attributes on parameters.

Easier object construction. In particular, then blocks in constructors may now reference the variables bound prior to the object construction..

override now required when implementing abstract and virtual members..

Structs and Enums implemented. See the informal language specification.

New switch --generate-filter-blocks. Generate filter blocks to allow first-chance exception catching for non-matching exceptions. Not on by default because some CLI implementations have problems with filter blocks.

C-style syntax for native functions. Writing PInvoke signatures in F# has been a little awkward since you have to reformat the signature in entirely tedious and boring ways. You can now just use the C syntax for a native signature, e.g.

    /// LAPACK/BLAS primitive matrix/matrix multiply routine
    [<DllImport(@"blas.dll",EntryPoint="dgemm_")>]
    extern void DoubleMatrixMultiply_(char* transa, char* transb, int* m, int* n, int *k,
                                      double* alpha, double* A, int* lda,double* B, int* ldb,
                                      double* beta,
                                      double* C, int* ldc);

    ///  C := alpha*op( A )*op( B ) + beta*C
    let DoubleMatrixMultiply trans alpha (A: FortranMatrix<double>) (B: FortranMatrix<double>) beta (C: FortranMatrix<double>) = 
        // Mutable is needed because F# only lets you take pointers to mutable values
        let mutable trans = trans  // nb. unchanged on exit 
        let mutable beta = beta 
        let mutable alpha = alpha 
        let mutable m = A.NumCols 
        let mutable n = B.NumRows 
        let mutable k = A.NumRows 
        let mutable lda = A.NumCols 
        // Call the BLAS/LAPACK routine
        DoubleMatrixMultiply_(&&trans, &&trans, &&m, &&n, &&k, &&alpha, A.Ptr, &&lda, B.Ptr, &&k, &&beta, C.Ptr, &&m)

Pattern matching on arrays. Several people have requested this OCaml feature.

Substantial tightening of #light rules. The #light syntax option was letting through many constructs that were clearly badly formatted. Extra tokens are now inserted based on indentation and column position to ensure that code conforms to the requirements of #light.

Reliable compiled names for parameters.

member syntax for object expressions. It is convenient and regular to support the member syntax used in class expressions in object expressions as well, as this allows you to move member bindings to and from object expressions without any syntactic adjustments, e.g.

    { new session with 
        member x.Interrupt() = interrupt()
        member x.Input       = inW
        member x.Output     = IEvent.filter nonNull outE
        member x.Error      = IEvent.filter nonNull errE
        member x.Exited     = exitedE      
        member x.Alive      = not proc.HasExited
        member x.Kill()         = killProcess proc
        member x.Completions(s) = completions(s:string) }

A namespace can now contain a module and type of the same name. An attribute annotation is required - see the F# library for examples (e.g. math/complex.fs). Greatly simplifies F# library design and implementation.

Library Changes and Reorganization

Physical Library Reorganization. After an extensive design review the mapping of F# modules to .NET namespaces and module names has been extensively revised. We've gone to great pains to ensure that almost no F# code will actually break because of this change: Most F# code does not refer to module by their long paths, and even for the code that does we've left lots of "deprecated" warnings in place and the compiler will generally ensure that old code works and will give advice about the new location of a construct so you can update your code at your own pace.

Why did we do this? Above all because the new mapping is very easy to explain, unlike the old one. This is very important as we come to write the F# books, and to expand the F# library over time, adn to set a good standard in library design practice with F#. Furthermore this is a really important step toward clarifying which parts of the previous library are "core" F# and which parts only exist for compatibility with OCaml.

The previous library mapping sort of grew over time: the split between FSLIB and MLLIB was never very clear, and there were just a whole heap of modules cluttered under MLLib, some of them very important indeed (e.g. List and even some things that had nothing to do with OCaml such as IEnumerable). The reorganized library design is, I think you'll agree, much cleaner, and much more along the lines of the .NET design.

The namespace layout is as follows. As part of the redesign we have added an attribute that allows a module and a type to co-exist in the same namespace.

Top level namespaces:

        fslib.dll:
            Microsoft.FSharp.Core     
            Microsoft.FSharp.Collections
            Microsoft.FSharp.Compatibility
            Microsoft.FSharp.Control
            Microsoft.FSharp.Math
            Microsoft.FSharp.NativeInterop
            Microsoft.FSharp.Quotations
            Microsoft.FSharp.Reflection
            Microsoft.FSharp.Text
            Microsoft.FSharp.Experimental

            Microsoft.FSharp.Tools.FsLex 
            Microsoft.FSharp.Tools.FsYacc
            
        mllib.dll:
            
            Microsoft.FSharp.Compatibility.OCaml  

Opened by default:


        Microsoft.FSharp.Core     
        Microsoft.FSharp.Core.Operators
        Microsoft.FSharp.Core.LanguagePrimitives
        Microsoft.FSharp.Collections
        Microsoft.FSharp.Control
        Microsoft.FSharp.Text

        Microsoft.FSharp.Compatibility.OCaml  

More detail:


        Microsoft.FSharp.Core
           type Ref
           type Option
           module Operators     
           module LanguagePrimitives     
           module {Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Float,Float32,String,Char}     
           module Ref
           module Option
           module Enum

        Microsoft.FSharp.Collections
           type List
           type SetQ, MapQ, HashSetQ
           type LazyList
           module {Array,Array2,Array3}
           module List
           module IEnumerable
           module LazyList
           module Map
           module Set
           module ResizeArray
           module HashIdentity
           module ComparisonIdentity

        Microsoft.FSharp.Control
           type IEvent
           type IDelegateEvent
           type ICompatEvent
           type Lazy
           module IEvent
           module Lazy
           
        Microsoft.FSharp.Math
           type BigInt
           type BigNum
           type Complex
           type Matrix<_>
           type Vector<_>
           type RowVector<_>
           module Matrix
           module Matrix.Generic
           module Vector
           module Vector.Generic
           module Notation
           module BigInt
           module BigNum
           module Complex
           module GlobalAssociations
           
        Microsoft.FSharp.Experimental
           type IPattern
           
        Microsoft.FSharp.NativeInterop
           module NativePtr
           type CMatrix
           type FortranMatrix
           type NativeArray
           type NativeArray2
           type PinnedArray
           type PinnedArray2
           
        Microsoft.FSharp.Quotations
           module Raw
           module Typed
           
        Microsoft.FSharp.Text
           module Printf

        Microsoft.FSharp.Text.StructuredFormat
           type IFormattable
           type Layout
           module LayoutOps
           
        Microsoft.FSharp.Text.Compatibility
           module CompatArray
           module CompatMatrix
           
        Microsoft.FSharp.Compatibility.OCaml  
          [Arg], [Big_int], [Buffer], [Bytearray], [Filename], [Hashtbl], [Lexing], [Num], [Obj], [Parsing], [Pervasives], [Printexc], [Sys]
       

Note that this has:

Seq as shorthand for IEnumerable. One of my friends said 'I fall asleep reading IEnumerable'. So we've introduced the type abbreviation

  type 'a seq = IEnumerable<'a>

and the module Seq. The latter is identical to IEnumerable except that you can write Seq.empty instead of IEnumerable.empty(). In the long term we may deprecate the module IEnumerable, but it is not yet marked deprecated.

New library functions. truncate and pairwise added to IEnumerable/Seq, pairwise added to IEvent. The function truncate places a maximum on the number of elements returned by the sequence. Pairwise returns a sliding window on the enumerable, i.e. elements (0,1), (1,2), (2,3) etc. For events pairwise does nothing on the first firing of the event and then returns (prior,current) pairs for each subsequent firing.

Optional Safer Collections. A recurring theme in the design of collection classes (in particular immutable ones such as Map and Set) is the desire to use the type system to track information about the comparison and hashing functions involved. Until now F# offered no way to be 'strict' about tracking this information. While this lack of 'strong typing' is standard for .NET collections, many F# and OCaml programmers tend to have a higher standard, where the type system can be used to ensure that values created using one comparison ordering aren't confused with values created with another ordering. This applies especially to Set values which support important binary operations such as union and difference. As such we've now adopted an (optional) type-tagging technique to ensure that users who want to can adopt this level of safety. Existing code will continue to work as normal. However, the Microsoft.FSharp.Collections.Tagged namespace now contains types that carry an extra type parameter, related to the comparison/hash function.

The changes mean you may use types like the following:

       Tagged.Set<'a,'compareTag>                      -- indicates a set using some kind of comparison
    or Tagged.Set >    -- indicates a set using structural comparison (identical to Set)
    or Tagged.HashSet >    -- indicates a hash set using reference comparison 

Here the tag variables just mark a lack of information about the comparison function.

       type SetUntagged<'a>         -- a set using some user-specified comparison function that we don't know anything more about
       type MapUntagged<'a>         -- a map using some user-specified comparison function that we don't know anything more about
       type HashSetUntagged<'a>     -- a hash set using some user-specified comparison function that we don't know anything more about

Custom tracked comparison tags can be created by defining new class to act as the tag, or by using the Set.MakeTaggged, Map.MakeTagged and Hashtbl.MakeTagged functions.

New Library Modules. ResizeArray - this module is the F# name for System.Collections.Generic.List.

Minor changes to NativeInterop namespace based on user feedback.. NativeArray.Create now called NativeArray.FromPtr. NativeTranspose members on CMatrix and FortranMatrix. New types PinnedArray and PinnedArray2.

UnverifiableAttribute. This attribute can be used to mark code that is potentially unverifiable.

Visual Studio: Goto defintition now works across projects and into the F# library.

Resources on the command line.resx resources may now be added to the F# command-line compiler and as files in the Visual Studio mode.

Cleanup of Parser and Lexer engine APIs. Old API functions deprecated. The two namespaces under Microsoft.FSharp.Tools contain the official F# APIs for using the parsing and lexing tools.

Library addition: Matrix.copy, Vector.copy, Array.copy.

Library addition: F# Immutable Map values now support the map.[i] syntax.

Library addition: Optionally safer collection types. F# Map, Set, HashSet and Hashtbl (HashMultiMap) values now use underlying SetQ etc. types that carry extra type annotation "qualifications" about the comparison and hashing functions assocaited with the collection.

Compiled names for modules now include a "Module" suffix if a RenamedModule attribute is given. Whenever you define a public module in F# code with this attribute, the compiled name of that module now has a "Module" suffix added. This is never visible from F# code unless you use reflection. This allows F# namespaces to contain a module and type of the same name, e.g. a module called List and a type called List. The rules of the F# language disambiguate between these automatically without the Module prefix ever being visible.

Deprecated Microsoft.FSharp.Idioms. Pretty much all the useful operations from this module are now in Microsoft.FSharp.Core.Operators, which is opened by default, or there are other reasonable choices, e.g. just use using instead of Idioms.using.

Removal of some long-deprecated library functions. Idioms.foreachG, List.transform etc.

Simpler OCaml-compatible Channel abstraction. in_channel and out_channel now map to TextReader/Writer, with a hidden BinaryReader/Writer. This leads to more generally usable printf and fprintf functions, and in particular removes the final dependency of the "true" F# library on the OCaml-compatible channel abstraction. This makes "printf" much easier to understand and explain, as it can be explained directly in terms of System.Console.Out.

printf and fprintf functions can now be used in conjunction with any TextWriter streams.

Properties removed from in_channel and out_channel. e.g. Stream, StreamReader, BinaryReader. Necessary in order to simplify the implementation and mapping of the channel abstraction above. Use the functions in the InChannel and OutChannel modules instead.

F#-specific functions and operator definitions removed from Pervasives and now in Microsoft.FSharp.Core.Operators.

Other Changes

New LAPACK sample..

Improved speed of bracket matching in Visual Studio mode..

F# library is now free of C# code. We had a few dangling bits of C# code in the library implementation, but they are now gone.

Remove renaming of F# library from static linking process. The --standalone flag used to rename Microsoft.FSharpp to FSharp, for no particularly good reason. This has been stopped.

F# console now implements TAB completion and history.

Bug Fixes

752     F# Compiler     object model members have lost their argument names
751     F# Compiler     type variable names and numbers are all messed up they are the inference type variable names)
724     F# Language     permit accurate names on arguments, especially for OO code (reported by Robert Pickering - thanks Robert!)
715     F# Compiler     RunClassConstructor XNA on xbox 360
748     F# Compiler     unicode chars not supported with FSI
652     F# Samples      Samples101 does not compile resources
719     F# Compiler     type checking reproted to differ with fscp10.exe
706     F# Compiler     custom attributes for fields
754     F# Compiler     support "out" parameter attributes
756     F# Language     permit attributes on parameters
765     F# Compiler     System.Runtime.InteropServices.Out on argument parameters does not generate an out parameter
737     F# Compiler     nested constructs (constants) lead to huge memory and time requirements
464     F# Compiler     lists, arrays, format strings not reporting error at right location
658     F# Compiler     Are we checking generalization conditions when implementing abstract or virtual generic methods (making type variables rigid is not enough! Must check we can generalize)
488     F# Compiler     "interface method unimplemented" errors (checked at end of scope) give a range that extends over the entire file
725     F# Library      stabilize LanguageServices API
767     F# Library      Map type missing a get_Item property for .[] notation
766     F# Library      Map module still missing to_list, of_list, to_IEnumerable etc.
774     F# Language     #light permitting several obviously incorrectly formatted expression forms
771     F# VS Mode      Cant right click and go to definition through to F# library
759     F# Documentation        spec and examples needed for high precedence application
508     F# VS Mode      Visual Studio mode does not report missing files and allows "builds" when files don't exist
661     F# VS Mode      GoTo Definition doesn't work for F# library definitions
772     F# Language     pattern matching on arrays requested
770     F# VS Mode      we're not showing XML help for .NET enumeration values
662     F# Language     Support comprehensions
763     F# VS Mode      Can't right click go to defenition
776     F# Compiler     uppercase member warning
778     F# Compiler     F# does not support C#-style \x1F characters
782     F# Interactive  lexer errors upset F# Interactive line error reporting
781     F# Compiler     use of "+" with "string" types doesn't detect that only reasonable return type is "string"
780     F# Compiler     reasonable indentation of a "with" record update gives a #light syntax error
779     F# Compiler     try/finally on a single line gives a #light error
760     F# Compiler     #light problems reported by Mort
762     F# VS Mode      F# VS mode pauses when scrolling pass a bracket-matching character
736     F# Interactive  AutoExpand is missing (except in the Visual Studio PlugIn version where it is mapped to TAB)
798     F# VS Mode      WINEXE option not available in Visual Studo
799     F# VS Mode      properties box looks kind of messed up in Visual Studio
800     F# Compiler     F# exceptions should be filtering rather than catching and rethrowing (Reported by rjblack - thanks Richard!)
720     F# Tools        fslex doesn't support \xHH
819     F# Language     support __SOURCE_DIRECTORY__
820     F# Library      support more instances of overloaded multiplication operator on Matrix, Vector and RowVector
821     F# Library      Floating point numbers such as 1.000000000001 get printed by auto-formatting as just "1"
822     F# Library      Redesign the NativeInterop module based on feedback from users and recent LAPACK work
823     F# Library      Add String.for_all and String.exists
827     F# Samples      Add LAPACK sample to distribution
828     F# VS Mode      Double check bracket matching is still working in Visual Studio mode
777     F# Compiler     lowercase static member gives an error
815     F# VS Mode      Type parameter contraint errors given against wrong file
812     F# Compiler     Red squiggly sprinkled randomly like confetti
806     F# Compiler     #light;; is not an interaction in fsi
818     F# Language     static property is interpretted as a method
802     F# Library      Revamp the module locations of the F# Library
833     F# Language     some long name lookups of constructors and fields not being handled correctly
835     F# Library      set and map values with different comparison functions are too easy to confuse
809     F# VS Mode      Installer fails on VS2003 machine - reported by Jan Sacha
837     F# VS Mode      another unicode bug using VFSI
836     F# Compiler     Jon Harrop's for-loop-in-constructor bug
795     F# VS Mode      intellisense not working in #light code
803     F# Language     cannot write a comprehension binding continaining "let" on a single line in the hardwhite syntax

Changes between v1.1.12.5 and 1.1.12.7

Disabled generation of tailcalls on Mono and .NET 1.0. A bug has been reported in Mono's implementation of tailcalls. The fscp10.exe compiler is for use on Mono and we have adjusted this to be a binary that does not itself either make use of nor generate tailcalls (except for immediately recursive functions, where tailcalls become branches). Additionally, the fslib10.dll and mllib10.dll libraries are used when running code on Mono and have been built with tailcall generation disabled. This situation will remain until Mono's implementation of tailcalls is completely robust.

Minor library additions. Added Array.tryfind

Bug fixes.

    692 18/09/2006      F# Compiler     FSI fails when creating delegate type
    694 19/09/2006      F# Interactive  delegate invoke (wrong arity?) falls over in FSI
    709 20/09/2006      F# Compiler     hash on arrays do not detect numberRemaining=0, stack-overflow on circular datastructures
    712 25/09/2006      F# Compiler     :? error with value types in expr
    710 29/09/2006      F# Compiler     offside1, offside2 etc.
    703 29/09/2006      F# Library      hashtable add throwing stack overflow exception
    708 30/09/2006      F# Compiler     #light interactive bug from Rob
    704 30/09/2006      F# Compiler     fsi --full-help generates same output as fsc --full-help
    716 30/09/2006      F# Visual Studio Intellisense does not work inside ill-formed lists (thanks to Ralf Herbrich)
    723 30/09/2006      F# Compiler     offside problem (reported by Dennis Hamilton - thanks Dennis!)
    728 30/09/2006      F# Library      UInt64.to_float and UInt32.to_float sometimes return incorrect results (reported by Dave Wecker - thanks Dave!)
    729 30/09/2006      F# Compiler     --help and --full-help not showing anything for fsc.exe
    738 02/10/2006      F# Library      Hashing big integers raises an exception

Changes between v1.1.12.2 and 1.1.12.5

High Precedence Application. A long-standing problem with the F# syntax is that method applications followed by property/field lookups such as obj.Method1(args).Method2(args).Property1.field2 have had to be written with very non-intuitive parentheses, e.g. ((obj.Method1(args)).Method2(args)).Property1.field2.

To fix this, this release incorporates a minor change in the F# syntax (with and with the #light syntax option). In particular, applications id(args) now have higher precedence (i.e. bind more tightly) than the dot-notation. This only applies when no spaces or other whitespace separate the identifier and the arguments.

--no-tailcalls now binary-format neutral. In prior versions the --no-tailcalls option was a global setting, hence requiring the use of special libraries that had tailcalls removed. Systems such as Mono now correctly support the .tail IL annotation and so a global version of this option is no longer required. The option is still supported, but will only affect the code being generated in the assembly currently being compiled and will not result in the selection of different runtime libraries.

Revert change to operator overloading made in 1.1.11.12.2 release.

The change to operator overloading in 1.1.11.12.2 was incorrect, as it disallows the use of legitimate .NET overloads. The upshot is that the basic operators now have the following signatures. These indicate that the two argument types and the return type may indeed all be different, and knowledge of the return type and the second argument type are not sufficient to resolve the overloading - a type annotation may be required to give the precise type of the first argument.

val inline (+)  : ^a -> ^b -> ^c when ^a : (static member (+)    : ^a * ^b -> ^c)
val inline (-)  : ^a -> ^b -> ^c when ^a : (static member (-)    : ^a * ^b -> ^c)
val inline ( * ): ^a -> ^b -> ^c when ^a : (static member ( * )  : ^a * ^b -> ^c)
val inline (/)  : ^a -> ^b -> ^c when ^a : (static member (/)    : ^a * ^b -> ^c)
val inline (%)  : ^a -> ^b -> ^c when ^a : (static member (%)  : ^a * ^b -> ^c)
val inline (mod): ^a -> ^b -> ^c when ^a : (static member (%)  : ^a * ^b -> ^c)

We are considering a design revision which would allow more restricted specifications of permitted overloads, but are currently erring on the side of generality, even at the cost of occasional additional type annotations.

Bug fixes.

700     F# Language     undentation should be allowed when () and {} immediately follow an "="
695     F# Compiler     record building construct - not checking records only not classes
702     F# Compiler     unbound type variable problems for inner constrained polymorphic definitions

Collected changes between v1.1.11.12 and 1.1.12.2

Lightweight syntax option. Are you sick of writing in? The #light option makes the use of certain keywords such as in optional by using indentation. See the informal language specification for details, as well as the ConcurrentLife sample and the Samples101 tutorial. Enable using #light.

First experimental cut at the Active Patterns. More details to follow on Don Syme's blog.

More modules in MLLib. Modules UInt8, Int8, Int16, UInt16 have been added.

More collections in Microsoft.FSharp.Collections. The Set and Map collections are now defined as object-oriented abstractions in Microsoft.FSharp.Collections. The corresponding MLLib modules are defined in terms of these OO abstractions.

Removed deprecated Stream module from MLLib. Minor updates to the LazyList module as a result.

--gnu-style-errors flag no longer accepts spurious integer argument.

Slight modification to overloading for +,*,/,mod.

In version 1.1.11 a slight change was made to the default overloaded signature for - operator to allow the return type to be unassociated to the two input types, as is required for overloading on the System.DateTime subtraction operator. This change was mistakenly applied to other operators, resulting in situations where type inference would report unexpected inference errors for fairly straight-forward floating point code.

Bug fixes.

    --- F# Compiler     -R clobbers DLLs with PDBs
    --- F# Compiler     no properties being generated for top level values
    605 F# Visual Studio VFSI scroll to caret does not always show input position
    643 F# Compiler     internal warning when unpickling override of abstract member
    655 F# Compiler     interface implementing methods marked private but included in modul_typ
    656 F# Compiler     Runtime exception TypeLoadException method 'Specialize'... tried to implicitly override a method with weaker type parameter constraints
    645 F# Debug        problems setting breakpoints in inner functions (reported by Jack Palevich - thanks Jack!)
    647 F# Compiler     lowercase constructors are incorrectly permitted
    654 F# Interactive  cannot declare delegate types interactively
    672 F# Visual Studio Unapplied methods should give signature of method overloads in error message
    671 F# Compiler     -R feature overwrites .dll file with .pdb file
    670 F# Compiler     protected access not permitted via member 'this' variables
    668 F# Language     L-R type inference with (fun x -> x * x * 1.0)
    667 F# Language     exceptions to carry line numbers?
    663  Fix broken codegen for generalized constrained polymorphic functions
    659 F# Visual Studio Intellisense does not work in a for .. to .. do line
    676 F# Visual Studio Inappropriate popup
    644 F# Language     execution and inference for record expressions is not always left-to-right
    533 F# Release      proper uninstaller
    517 F# Compiler     fsi.exe does not process #r/#I directives for files on command line
    678 F# Library      delete very old obsolete functionality fro the 'Set' module
    679 F# Library      Add object-oriented version of immutable 'Sets' to Microsoft.FSharp.Collections
    681 F# Visual Studio hardwhite intelisense
    682 F# Compiler     field and property names with same name - allowed
    680 F# Visual Studio intelisense bugs
    665 F# Language     exprs ending in semi-expr sequences cause confusion when ending constructs which are themselves semi separated.

Changes between v1.1.11.7 and 1.1.11.12

Copy-Local reference options DLLs that are not in the GAC must be copied to an application's directory prioer to execution. This is not currently well-supported by the F# Visual Studio mode. Thus the following options are now supported by the fsc.exe compiler and are especially recommended for use from Visual Studio:

  -R           DLL     both reference the given DLL and copy it to the output directory at the end of compilation
  --copy-local FILE    copy the given file to the output directory at the end of compilation

Note that -R = -r + --copy-local. Also these switches are not required by fsi.exe which is able to resolve and load DLLs from any location.

New Installer InstallFSharp.msi. This currently always installs to the Program Files directory.

New library module Microsoft.FSharp.MLLib.Native Helpers for native interop. See library documentation.

Minor breaking change for native pointers. The F# "'a nativeptr" is now compiled as the .NET type System.IntPtr for all 'a. .NET pointers such as "int*" are now represented by "ilsigptr<int>" types. This cange is because although .NET has a notion of a "pointer type", used in some .NET signatures, these are not "real" types, since they can't be used within generic instantiations. This is very bad for C-interop F# code, which generates generic instantiations for function and tuple values. Thus, the F# 'a nativeptr type is now always compiled as System.IntPtr, regardless of 'a (it is not type equivalent as far as F# is concerend - this is just how the type is compiled. The pseudo-type 'a ilsigptr (IL Signature Pointer) is provided if you need to call a .NET signature using a pointer type.

COMPILED and INTERACTIVE supported as standard --define in F# Interactive and compiled code This is useful as some code fragments such as Application.Run() are only needed in compiled code. Also accessing things such as resources can vary between interactive and compiled code.

Type Inference corrections for fields and records

It is implicit in the F# informal specification that record constructions should use contextual left-to-right type information to help determine the type being constructed. This is now implemented, and makes it easier to use record syntax when record member names overlap.

Types are no longer inferred from uses of class field labels alone. Previously, defining a class "C" with a value field called, say "f" meant that "f" became a scoped record label. This meant that "expr.f" would infer the type of "expr" to be "C". This is still done for _record_ labels, but is no longer done for class field labels, and instead an annotation may be needed to constrain the type of "expr" based on left-to-right type inference. A helpful warning about the deprecation of this language feature is given when this occurs. This was always meant to be the intended treatment of inference for these constructs - it was an artefact of the initial implementation that inference for record field labels was treated in this way.

Various .NET generic constraints implemented .NET generics supports a number of somewhat adhoc constraints on the structural properties of types. It is necessary for F# to support these in order to emit correct and valid generic code and make sound use of F# libraries. The syntax of the constraints is:

   when 'a : struct       // any struct, with the exception of Nullable
   when 'a : not struct   // any reference type - note - this syntax is under revision
   when 'a : (new : unit -> 'a)   // default constructor

The following F#-specific constraint has also been added:

   when 'a : null          // any reference type that supports null according to the F# pseudo-enforcement rules for prohibiting the use of null with F# types
   when default 'a : <type>  // the variable will take the given value if not otherwise instantiated or generalized

Default constructors are called using the syntax:

   new 'a()

Where 'a should be related to another annotation in the same definition, e.g. an argument of the enclosing function. This constructs is compiled as a call to System.Activator.CreateInstance<'a>().

Minor improvements and Bug Fixes

   573  F# Compiler     list equality is not tail recursive.
   613  F# Library      List.combine and List.split are not tail recursive (reported by Ralf Herbrich - thanks Ralf!)
   615  F# Interactive  FSI reflection code throws TypeLoad error for type reference within the same interaction.
   602  F# Compiler     name of type not reported in "member required" error
   120  F# Compiler     Things stored in public static fields should only be accessible via properties
   495  F# Compiler     SQL cannot load F# assemblies due to publically writable statics
   625  F# Compiler     Poor error location for error messages related to 'new' in signatures
   626  F# Library      Add 'generate' methods to IEnumerable.
   628  F# Compiler     nested ifdefs not always handled correctly (Reported by Jack Palevich - thanks Jack!)
   630  F# Compiler     Error writing assembly with F# 1.1.11.7 (reported by Lewis Bruck - thanks Lewis!)
   631  F# Compiler     System.MethodAccessException thrown by FSI.EXE (reported by Pierre Dangauthier - thanks Pierre!)
   634  F# Compiler     object expression limitations: let bound object expressions not generalized (reported by Greg Neverov - thanks Greg!)
   640  F# Compiler     record fields should be inferred from the known context type of the expression 
   639  F# Compiler     class fields are contributing to the record field environemnt
   638  F# Compiler     multiple constraints on type parameters not being correctly printed
   636  F# Compiler     simple object expressions implementing interfaces should be allowed in "let rec" without generating an iniitalization graph warning
   632  F# Debug        smoother debugging needed for inner recursive functions
   648  F# Library      Documentation for printf codes for 64-bit integers is incorrect (reported by Richard Mortier - thanks Richard!)
   650  F# Compiler     incorrectly permitting the declaration of interfaces that contain fields (reported by Robert Pickering - thanks Robert!)
   649  F# Compiler     bug in quotation template filling for typed quotations (Reported by Tomas Petricek - thanks Tomas!)
   646  F# Compiler     attributes on top level values not propagating to generated static fields, e.g. ThreadStatic (reported by Robert Pickering - thanks Robert!)
   645  F# Debug        setting breakpoints in inner functions sort of broken (reported by Jack Palevich - thanks Jack!)

Changes between v1.1.11.6 and 1.1.11.7

Minor improvements and Bug Fixes

    --   Fix to permit the use of lambdas taking multiple tupled arguments within quotations.
    --   Fix integer formats 0b101001 and 0o101030 in fsi.exe
    --   Fix inlining of composition operator
    --   Add signature to 'prim-types', hiding the presence of the "Basics" module
    --   Fix optimization of integer keys for hash tables

Changes between v1.1.10.3 and 1.1.11.6

F# Language: Namespaces.. Multiple namespaces fragments now permitted in a single file. Multiple fragments can also be constrained by a single signature. Multiple different files within an assembly may also contribute to the same namespace. For example:

  /// Put the concrete type definition under 'Types'
  namespace Microsoft.FSharp.Math.Types
  
  type BigComplex = { r: bignum; i: bignum }
  
  /// Now add a type abbreviation and module under the main namespace
  namespace Microsoft.FSharp.Math
  
  type bigcomplex = Microsoft.FSharp.Math.Types.BigComplex
  module BigComplex = begin
    open Microsoft.FSharp.Math.Types
    let complex  r i = { new BigComplex with r=r;i=i }
  end

F# Language: Use of null values no longer require type annotations. null values previously required immediate type information. Instead, null constraints have now been incorporated into the inference process, meaning that the type associated with the use of the null value must simply be resolved at some point in the type inference scope. This means far fewer type annotations are needed when passing 'null' values to .NET.

F# Language/Library: Implementation of Structural comparison, equality and hashing now in F# code (hence easier to understand and debug). See the file prim-types.fs in the library for the implementation of the definition of structural and physical equality, used if all other optimization techniques fail.

F# Language: More General Type Checking Rule for Class Field Access and Setting. Accessing and setting a class field previously required the object being accessed to have precisely the type of the class containing that field. This has been liberalized so that the object can have any subtype of the class containing the field. This change may affect code that uses signatures, because the inferred type of a function may be more general. For example, given

  type MChan = 
    class
       val mutable sndLst : MChan list
    end

  let linkMChan src dstLst = src.sndLst <- append src.sndLst dstLst

the inferred type of linkMChan was previously

  val linkMChan : MChan -> MChan list -> unit

but is now the more general

  val linkMChan : #MChan -> MChan list -> unit

where as usual the # indicates that any subtype is accepted as the first argument. If no subtyping is required then a rigid type annotation may be used in the implementation:

  let linkMChan (src : MChan) dstLst = src.sndLst <- append src.sndLst dstLst

F# Language: Overload Resolution when Multiple Overloaded Operators Exist. Some .NET types support multiple overloads for the same operator, which must be resolved according to a process similar to the resolution of overloaded methods. F# uses constraints to handle operator overloading, and now resolves the choice between multiple overloads using essentially the same technique as is used to resolve method overloading. For example, the following overloads now resolve correctly:

  let f1 (x:DateTime) (y:TimeSpan) : DateTime = x - y
  let g1 (x:DateTime) (y:DateTime) : TimeSpan = x - y
  // Return type is also sufficient:
  let f2 (x:DateTime) y : DateTime = x - y
  let g2 (x:DateTime) y : TimeSpan = x - y
  // Just argument types are also sufficient:
  let f3 (x:DateTime) (y:TimeSpan)  = x - y
  let g3 (x:DateTime) (y:DateTime)  = x - y

F# Language: Type Qualified Disciminator Names. Ambiguity between constructors of a discriminated union can now be resolved by using the type-qualified path to the discriminator, for example:

    type XY = X | Y
    type YZ = Y | Z
    
    let y1 = XY.Y
    let y2 = YZ.Y
    
    let f xy = 
      match xy with 
      | XY.X -> "X"
      | XY.Y -> "Y"

    let g yz = 
      match yz with 
      | YZ.Y -> "X"
      | YZ.Z -> "Y"

The same is true of record field names, though this has been the case for some time now.

New F# Samples: DirectX 3D Visualization, WebCrawl. See the 'samples' directory.

F# Library: Warnings now given that 'Stream' will be renamed. This module has been renamed 'LazyList'.

F# Library: BigNum performance improvements. Major implementation improvements and tuning the cross-over between the multipliers.

F# Library: Additional Math.Complex operations.

F# Interactive and Library: Default floating point format for generic printing now 'g10'. i.e. for print_any, output_any, etc. and F# Interactive.

F# Interactive: --codepage switch now accepted by fsi.exe. This controls the codepage used to read the input files. The switch does not yet apply to fsc.exe.

F# Library: Primitive structural comparison and hashing routines moved. These were in Microsoft.FSharp.Primitives.CompilerPrimitives but are now under Microsoft.FSharp.LanguagePrimitives. After a review of the library and as part of the re-implementation of structural comparison and hashing in F# code (see below) the primitive functions used for polymorphic recursive calls in structural comparison and hashing have been moved to a new module Microsoft.FSharp.LanguagePrimitives. These functions may have been called recursively from some user code. The section in the language specification has been updated to reflect this.

F# Compiler: Optimizations and Code Quality. Fewer locals are now produced in many situations where inlining occurs. This improves the quality of the end x86 code, allows the JIT to inline more often and reduces the size of the metadata in generated assemblies.

Extensible expr.[idx] syntax for string, array, dictionary and other access operations.. The syntax expr.[idx] is now shorthand for accessing the Item property on a type. This means that expr.[idx] can be used to perform lookups on essentially any .NET collection type.

Note: As with overloaded operators on integers, the types string and the array types do not in reality support Item properties in the underlying .NET metadata. However F# arranges things to give the appearance that they do.

F# for Visual Studio: Minor improvements

F# Interactive: Suffixes .fsx and .fsscript now accepted.. These are useful for F# Interactive scripts.

F# Interactive: Formatting options may now be specified. There is an fsi object, of type InteractiveSession, available in the top-level.

  namespace Microsoft.FSharp.Compiler.Interactive
  type InteractiveSession 
    with
      member FloatingPointFormat: string with get,set
      member FormatProvider: System.IFormatProvider  with get,set
      member PrintWidth : int  with get,set
      member PrintDepth : int  with get,set
      member PrintLength : int  with get,set
      member ShowProperties : bool  with get,set
      member ShowIEnumerable: bool  with get,set
      member PrintIntercepts: (StructuredFormat.IEnvironment -> obj -> StructuredFormat.Layout option) list with get,set
      member AddPrinter: ('a -> string) -> unit
      ...
    end

Here's an example of it's use:

  > fsi;;
  > fsi.FloatingPointFormat <- "%.3";;
  > fsi.PrintWidth <- 80;;                                    
  > fsi.AddPrinter(fun (x:System.DateTime) -> sprintf "%Ld" x.Ticks);;
  > System.DateTime.Now;;
  > fsi.ShowIEnumerable <- false;;
  > fsi.ShowProperties <- false;;

F# Compiler: The --base-address flag. Base addresses indicate the default loading address for DLLs within a memory space. Loading a DLL at a default location can reduce the need for 'fixups' that occur when a native DLL gets relocated. Native DLLs occur with F# code if you use NGEN with your F# DLLs, and it is recommended that you use an appropriate base address if rebasing conflicts occur when using NGEN. Various tools and debuggers are available on the web to help determine if rebasing is occuring.

F# Compiler and F# Interactive: Use F# with Microsoft internal or self-built versions of the CLI. Some Microsoft internal or self-built implementations of the CLI have unusual, non-standard names such as v2.0.x86chk. The --cli-version flag can now be used to specify such a version.

F# Interactive: Minor improvements

Minor improvements and Bug Fixes

    574 F# Compiler     issue with top level mutables (fsi.exe), reported by Andrew Fitzgibbon
    389 F# Perf         Printf implementation allocated too many closures
    594 F# Compiler     tyvar lookup failed in ilreflect
    595 F# Interactive  F# Interactive code generation bug when closures used inside interface implementations
    596 F# Interactive  F# Interactive code generation bug: Implementing generic interfaces does
                            not always correctly work around Reflection.Emit limitations
    586 F# Compiler     local mutables spilled into other locals prior to use
    588 F# Compiler     expr of constructor argument is not typed-expr
    587 F# Compiler     poor error message on for i = 0 to 10 do .. done expr
    590 F# Compiler     match exprA,exprB with ....  allocates tuples
    592 F# Compiler     poor error message when a constructor is too generic
    582 F# Compiler     fsi prints types of the latest interaction with full path
    581 F# Compiler     Problem with pickling: Quotation <@ 1.3 @> gives NaN
    576 F# Perf         Reduce number of generated IL locals
    566 F# Compiler     interface inheritance/extension not being printed correctly
    471 F# Compiler     Eliminate unnecessary .cctors
    ---                 Fixes to printing and Array2 module for  non-zero-bounded multi-dimensional arrays.
    ---                 Instance members now permitted on types that may use null as a representation. They
                        are compiled as static members.
    ---                 Fields in super classes not accessible (reported by Ralf Herbrich - thanks Ralf!)

Changes between v1.1.10.2 and 1.1.10.3

The 'a nativeptr type. The unverifiable type constructor nativeptr is now supported for C/C++/C# pointer types, e.g. sbyte* becomes sbyte nativeptr. In principle this is a breaking change, as previously .NET pointer types were mapped to the F# type nativeint, and are now mapped to nativeptr instead. The new behaviour is, however, consistent with .NET and necessary to permit methods that overload by pointer type (e.g. the unverifiable System.String constructors accepting byte pointers) to be resolved correctly.

Minor improvements and Bug Fixes

Changes between v1.1.9.1 and 1.1.10.2

F# Interactive for Visual Studio. It rocks! See the section above.

F# website now at http://research.microsoft.com/fsharp

Unified, first-class, composable events. .NET events can now be accessed directly through their real name (e.g. form.Click) rather than through their helper functions (form.add_Click etc.). They can also be used in a first-class way, i.e. form.Click can be passed around as a value. The type of such a value is Idioms.IDelegateEvent, which extends Idioms.IEvent. F# published delgate types should have type Idioms.IHandlerEvent. An MLLib module Microsoft.FSharp.MLLib.IEvent includes some basic polymorphic operations over IEvent types.

Quotation processing over raw quoted expressions. New quotation operators such as <@@ @@> are supported for quoting terms (expressions) in their raw form. More details can be found in the documentation on the Quotations module and the F# informal language specification.

Removed Drop-Down VS Discrimination Menus. Temporarily disabled discrimination drop-down Intellisense in VisualStudio, due to poor completions.

Minor improvements and Bug Fixes

Changes between v1.1.8.1 and 1.1.9.1

Minor improvements and Bug Fixes

Minor syntax extension related to struct. The syntax module X = begin ... end can now be used in addition to the OCaml-compatible syntax module X = struct ... end. The use of the word struct is potentially ver confusing to .NET-savvy newcomers, who will confuse this with a C# struct. Likewise module X : begin ... end is now the recommended way of writing module X : sig ... end in signatures.

Address-of operator. Occasionally a need arises to pass a byref parameter on to a function. This can now by done using the '&expr' address-of operator. A warning will be given whenever this is used.

Source cleanup. Various cleanup work items completed.

ExportAs deprecated. ExportAs was an old, somewhat half-baked technique to export functions as classes. Now that the object model has been implemented it is no longer needed.

Changes between v1.1.7.0 and v1.1.8.1

Matrix library redesign and cleanup. Microsoft.FSharp.Math has been reorganised.

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.

Fix some problems with the Visual Studio mode. Some files were missing.

Changes between v1.1.5.2 and v1.1.7.0

Expression Quotation. Microsoft.FSharp.Experimental.Lifted (NOTE later renamed to 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.

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 includes the source code to the Abstract IL, ILX, the F# compiler, F# interactive, the library and the tools, as long promised.

Compiling: To compile it up you us the Makefile and the F# compiler from the distribution itself, and you currently need .NET 2.0, and there is some C/C++ helper code to compile which requires the use of the Microsoft Visual Studio 2005 C/C++ compiler. However you do not really need to compile the C/C++ code, which only enables debugging support etc. (and indeed you can reuse the absilsuppc.dll from the F# distribution itself instead of compiling it up afresh). It should be fairly straightforward to compile with .NET 1.0/1.1 (--cli-version 1.0, change define GENERICS to NOGENERICS etc.) and should also be possible to compile on Mono using 'fscp10.exe', the portable bootstrapped compiler.

General comment: The source has its many quirks and there are many things in we will be cleaing up - if it's ugly then please be merciful and ignore it. Anyway, have fun with it!

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). For example:

    val open_in_gen: flags:open_flag list -> permissions:int -> filename:string -> in_channel

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 as the way of creating function types.

Library Updates.

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 (new TransactionScope()) (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 undocumented Idioms.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

  

module Microsoft.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

Changes between v1.1.3.2 and v1.1.5.2

Matrix Library. Microsoft.FSharp.Math.Matrix<_> has been added as a generic matrix type, with extensive MATLAB-like operations at Microsoft.FSharp.Math.MatrixOps<_> and Microsoft.FSharp.Math.MatrixOps.Generic;. The former are for floating point matrices Matrix<float> = matrix, and the latter are generic over all matrix types. The interface to this library is likely to be stable. Vector and RowVector types are also defined - their status sill undergo revision after a few releases.

Very Preliminary Linear Algebra. Microsoft.FSharp.Math.LinearAlgebra<_> contains a handful of basic linear algebra functions.

Compositional, Customizable Structured Printing. A preliminary but powerful approach to user-definable structured display of terms has been implemented in this release. The solution is different to the OCaml-style "Format" library and is instead based on the generation of intermediary "layout" objects. So far, a layout describes how words will fit next to each other and where the breaks (and indentations) will/can be.

A layout engine typically constructs most layouts using a generic algorithm based on the term structure of F# data accessed via Microsoft.FSharp.Experimental.Reflection. Types that wish to customize their structured format specification can implement the StructuredFormat.IFormattable interface, which must provide a function that generates a StructuredFormat.Layout value. An environment is passed to the object that provides a function to use to generate layout for recursive calls. Leaf objects such as numbers and strings can be left unformatted, which gives a formatting engine control over how these appear (e.g. culture specific formatting of numbers). A default formatting engine is provided in Microsoft.FSharp.MLLib.Pervasives.LayoutOps for formatting layouts to strings, channels and text buffers. This engine can be customized to some extent (e.g. by print width, depth, culture and floating-point number formatting) and is used by thw following functions:

as well as the F# Interactive pretty printer. The end result is that objects are converted to textual formats consistently and in a customizable way. Here is and example of the output generated, here for a matrix holding further matrices:

> open Math;;
> open MatrixOps.Generic;;
> let m = matrix [[1.0;2.0;3.0]];;

val m : Matrix<float>

> m;;

val it = matrix [[1.000000; 2.000000; 3.000000]]

> let m = matrix [[m];[m];[m]];;

val m : Matrix<Matrix<float> >

> m;;

val it = matrix
          [[matrix [[1.000000; 2.000000; 3.000000]]];
           [matrix [[1.000000; 2.000000; 3.000000]]];
           [matrix [[1.000000; 2.000000; 3.000000]]]]

Here is an example of customization of the structured layout to format complex numbers, without actually specifying the formats of the constituent components:

open StructuredFormat.LayoutOps
type Complex = { real: float; imaginary: float }
  with 
    member x.r = x.real
    member x.i = x.imaginary
    interface StructuredFormat.IFormattable with
      member x.GetLayout(env) = 
        objL (box x.r) ++ rightL "r" ++ sepL "+" ++ (objL (box x.i) $$ rightL "i")
    end

Named arguments for attributes. Attribute specifications can now take named arguments, e.g.

[<DllImport("KERNEL32.DLL", EntryPoint="MoveFileW",  SetLastError=true,
                            CharSet=CharSet.Unicode, ExactSpelling=true,
                            CallingConvention=CallingConvention.StdCall)>]
let MoveFile ((src : string), (dst: string)) : bool = failwith "extern"

Abstract properties. Interfaces and classes may now define abstract properties and specify overrides and defaults for these. This is functionality that was not completed in the first release of the object model. e.g. in an interface definition:

Abstract properties and properties in interfaces. Interfaces and classes may now define abstract properties and specify overrides and defaults for these. This is functionality that was not completed in the first release of the object model. e.g. in an interface definition:

type IEnvironment = 
  interface
    /// A property indicating the maximum number of columns
    abstract MaxColumns : int
    /// A property indicating the maximum number of rows
    abstract MaxRows : int
  end

And in an implementation by a class:

type MyEnvironment = 
  class C
    interface IEnvironment with
      method x.MaxColumns = 3
      method x.MaxRows = 4
    end
  end

And in an implementation by an object expression:

{ new IEnvironment 
    with MaxColumns = 3
    and  MaxRows = 4 } 

Rename 'MLLib.Vector' to 'MLLib.ReadonlyArray'. 'Vector' and 'vector' are now used for Microsoft.FSharp.Math.Vector, mutable column vectors whose element type typically support certain element operations.

Bug Fixes.

470        F# Compiler     Constructors and method can't be overloaded betweeen 0/1 arguments
473     F# Compiler     Operator overloading bug
474     F# Visual Studio Pattern hints for lists showing operator names, also no testing for these
475     F# Visual Studio Pressing BAR causes poor menus to pop up in Visual Studio too often
478     F# Compiler     #use only processes one interaction per file
479     F# Compiler     fsi - ctrl-C during command line arg processing unhandled.
481     F# Compiler     fsi - syntax error recovery...
482     F# Language     any_to_string doesn't print arrays
483     F# Compiler     internal type variable error (reported by Karthik)
484     F# Compiler     overloaded indexer properties not correctly resolved (from F# Mailing list)
485     F# Compiler     uppercase non-constructor names used in patterns do not give a warning
486     F# Doc          Fix documentation bug (reported by Greg Chapman - thanks Greg!)
491     F# Library      Equality not implemented on matrices
492     F# Compiler     imperative type vars and type var bindings not being shown in error messages (reported by Karthik)
391     F# Compiler     F# not automatically usable on x64 boxes
372     F# Compiler     F# gives syntax error for OCaml top level expressions 
349     F# Compiler     Inferred constraints of the form "x :> obj" should be ignored (e.g not required in signatures)
250     F# Visual Studio Load on-the-fly XML documentation into Visual Studio, or connect to VS interfaces that will do this for us
309     F# Compiler     import C# constrained polymorphism as F# constrained polymorphism
315     F# Visual Studio output does not go to console window by default
490     F# Library      Consistent approach to structured print layout needed

Changes between v1.1.2.0 and v1.1.3.2

Bug Fixes. Various minor fixes to F# Interactive, e.g. large bytearrays. F# Interactive now works on .NET 2.0 Relase Candidate versions. Additional warnings on some minor incomplete features.

Changes between v1.1.1.6 and v1.1.2.0

Visual Studio. Now supports "Go To Definition" and "Go To Declaration"

MLLib.Printf. Now supports '%M' for decimal values and '%O' for any 'any' object value. These are currently printed using Object.ToString() but may in the future be printed using any_to_string.

Bug Fixes. Visual Studio fixes for '|' triggers.

Core Language. Integer constants for the types 'bignum' and 'bigint' are now supported, e.g.

do Printf.printf "%O\n" 3N
do Printf.printf "%O\n" 3I
do Printf.printf "%O\n" (3N / 4N)
do Printf.printf "%O\n" (3N / 400000000N)
do Printf.printf "%O\n" (3N / 3N)
do Printf.printf "%O\n" (-3N)
do Printf.printf "%O\n" -3N
do Printf.printf "%O\n" (-3N / -3N)
do Printf.printf "%O\n" -30000000000000000000000000000000000000000000000000000000000000N

The following operartors are now supported and can be used for multi-dimensional array lookup/assignment.

   arr.(i,j)          -- Look up a rectangular (non-jagged) 2D array of type 'ty[,]'
   arr.(i,j) <- x     -- Assign into a  rectangular (non-jagged) 2D array of type 'ty[,]'
   arr.(i,j,k)        -- Look up a rectangular (non-jagged) 2D array of type 'ty[,]'
   arr.(i,j,k) <- x   -- Assign into a  rectangular (non-jagged) 2D array of type 'ty[,]'

The MLLib modules Array2 and Array3 provide basic operations for 2 and 3 dimensional arrays. .NET operations on the System.Array type can also be used directly.

Library. The Compatibility.CompatArray and Compatibility.CompatMatrix module now give better results (no polymorphism restrictions apply) if inadvertantly used from .NET 2.0. Use of these modules is not recommended from .NET 2.0 but sometimes occurs when code is copied from cross-compiling samples.

Changes between v1.1.0.4 and v1.1.1.6

Attributes. Specification clarifications for attributes. Attributes now give warnings when used inappropriately. Attributes can now be referenced with or without the Attribute suffix, e.g. [<Obsolete("this function is obsolete")>] or [<ObsoleteAttribute("this function is obsolete")>].

Compilation Speed Optimizations. Improved compilation speeds, especially when using the --standalone flag.

VS Mode. Better response as now compacts less often. Now accepts all fsc.exe flags within the argument window: those irrelevant to type-checking are still used when the command line compiler is invoked.

Minor renamings. The .NET compiled names of some exceptions have changed to follow .NET library design guidelines

The names from F# code are now either the above names or, when using MLLib, the equivalents Assert_failure, Match_failure and Undefined.

Turning off default augmentations for discriminated unions. By default F# dsicriminated unions are augmented with properties and methods such as member IsRed : bool,member Red : int -> Color and Red1 : Color -> int for a constructor Red of int in a type Color. Now that augmenetations are supported directly in the F# language it is often more convenient to manually design these augmentations. The default augmentations can now be suppressed by using the [<DefaultAugmentation(false)>] attribute. For example, the Option<'a> type in the F# library is defined as:

    []

    /// The type of optional values.  When used from other .NET languages the
    /// empty option is the 'null' value.
    type Option<'a> = None | Some of 'a

    /// Augmentation
    type Option<'a> 
      with
        member x.Item = match x with Some x -> x | None -> op_Raise (new System.IndexOutOfRangeException())
        static member IsNone(x : Option<'a>) = match x with None -> true | _ -> false
        static member IsSome(x : Option<'a>) = match x with Some _ -> true | _ -> false
        static member None : Option<'a> = None
        static member Some(x) : Option<'a> = Some(x)
      end

Initial support for Microsoft.FSharp.Experimental.Collections With the completion of the F# support for members and augmentations we are moving the functionality of the MLLib collections to be co-designed libraries for functional and object oriented programming. The means that a functional programming API to the collection types will be offfered in MLLib, and a mixed object-oriented/functional API within FSLib. This will greatly improve the usability of the collection types from C# and other .NET languages, without losing the essence of OCaml-compatible ML programming. The first class we have applied this treatment to is Microsoft.FSharp.Experimental.Collections.HashTable and the related HashSet, CHashTable and CHashSet.

Generic Recursion support temporarily withdrawn. Some bugs were found in the support for generic recursion added in 1.1.0.4 (unverifiable binaries could be produced in some situations). In particular, full signatures need to be given to make a function eligible for generic recursion, and this is not yet enforced. Functions and values may still be given explicit type parameters, but recursive uses of explicitly paramaterized values must at invariant instantiations, as was always the case for versions prior to 1.1.0.4.

Bug fixes. Several bug fixes related to attributes, generalization, enumerators and exception abbreviations, Arg.usage. Thanks to Martin Churchill, Dominic Cooney, SooHyoung Oh, Ondrej Rysavy, Robert Pickering, Greg Lee and Adam Granicz among others for reporting these bugs. Some other bugs recently recorded as fixed in out database are as follows:

443        F# Library  MLLib.Stream incorrect behaviours
442     F# Compiler print_any raises exceptions on singleton constructor values
452     F# Compiler Visual Studio and fsc.exe both have problems with unicode, reported by DOminic Cooney
440     F# Tools    lex/yacc - partial parses of stdin require extra token before succeeding and discard buffered input
441     F# Compiler uncaught exceptions are not reported in user friendly way (no details of what they carry...)
444     F# Compiler records compile to classes with duplicate members names - a problem for debugging
445     F# Compiler serialisation of nil list fails
426     F# Compiler "end of file in string or comment" error doesn't report start-of-string-or-comment
459     F# Compiler Undefined type variable problem
458     F# Compiler typechecker doesn't decode all attributes correctly (decode_simple_cattr_data)
371     F# Compiler Support adding managed resources to .NET DLLs and EXEs
422     F# Compiler VideoPlayer sample gives error
406     F# Library  Bignums package
470     F# Compiler Constructors and method can't be overloaded betweeen 0/1 arguments
467     # Library   any_to_string on char fails on 1.1

Compiler for use with Mono.

Later note: as of F# 1.1.12 when used with Mono 1.1.17 the comiler for Mono is fscp10.exe and tailcalls appear to be correctly supported by Mono.

Old note: The binary fscp10ntc is a version of the F# compiler that is reported to work to some extent in conjunction with the Mono CLI implementation. Tailcalls have reported to cause problems on Mono, hence this is a "no tailcall" (ntc) version of the compiler, which leads to changes in performance. The matching "ntc" versions of the libraries are also included. This is also a CLI 1.0 binary, again changing the performance.

This version of the compiler is reported to be sluggish, so a reasonably fast machine may be required. It may also be worth investigating the use of pre-compilation (mono --aot) in conjunction with this binary to improve startup times (pre-compilation is pretty much essential for any compiler).

Changes between v1.0.8.6 and v1.1.0.4

The F# Object and Encapsulation Extensions. F# types can now be augmented with properties, members and operators. Furthermore, .NET-style class and interface types may also be defined in F# itself. Fairly complete documentation is provided in the language specification.

Big integers and arbitrary sized rational arithmetic. The types under Microsoft.FSharp.Math.* are the implementations of the F# arbitrary precision integer and rational arithmetic types. A partially-OCaml-compatible version of this functionality is included in MLLib, i.e. use the functionality available via 'open Num'. The types support overloaded operators. The naturals are used to build arbitrary sized integers and rationals. The implementation aims to for a lower garbage cost and provides multiplication that scales effectively up to huge numbers.

The F# Language Specification (Preliminary). A work-in-progress language specification is now included in the manual.

Specification clarifications.

Managed and Unmanaged Resource Linking. The command-line flags --resource, --link-resource and --win32res are now supported by the F# compiler for embedding native and managed resources (text files, icons, bitmaps, audio files etc.) into executables. They have the same meanings as the corresponding C# flags.

New in Microsoft.FSharp.Idioms. The following are new in this module of useful .NET idioms:

val foreachE: (_ :> System.Collections.IEnumerator) -> ('a -> unit) -> unit
val foldeachE: (_ :> System.Collections.IEnumerator) -> 'acc -> ('acc -> 'a -> 'acc) -> 'acc
val transformE: (_ :> System.Collections.IEnumerator) -> ('a -> 'b) ->  System.Collections.IEnumerator

val foreach: (_ :> System.Collections.IEnumerable) -> ('a -> unit) -> unit
val foldeach: (_ :> System.Collections.IEnumerable) -> 'acc -> ('acc -> 'a -> 'acc) -> 'acc
val transform: (_ :> System.Collections.IEnumerable) -> ('a -> 'b) ->  System.Collections.IEnumerable

#if GENERICS
val foreachG: (_ :> System.Collections.Generic.IEnumerable<'a>) -> ('a -> unit) -> unit
val foldeachG: (_ :> System.Collections.Generic.IEnumerable<'a>) -> 'acc -> ('acc -> 'a -> 'acc) -> 'acc
val transformG: (_ :> System.Collections.Generic.IEnumerable<'a>) -> ('a -> 'b) ->  System.Collections.Generic.IEnumerable<'b>

val foreachEG: (_ :> System.Collections.Generic.IEnumerator<'a>) -> ('a -> unit) -> unit
val foldeachEG: (_ :> System.Collections.Generic.IEnumerator<'a>) -> 'acc -> ('acc -> 'a -> 'acc) -> 'acc
val transformEG: (_ :> System.Collections.Generic.IEnumerator<'a>) -> ('a -> 'b) ->  System.Collections.Generic.IEnumerator<'b>
#endif

type 'a sizeof = { result: int }
val inline sizeof: unit -> $a sizeof


Bugs fixed.

    438     F# Compiler     Mixed null and string matches bypassed pattern simplifier
    441     F# Compiler     Uncaught exceptions wrapping a string report their message.
    442     F# Compiler     Experimental.Reflection failed on singleton constructor values.
            F# VS Mode      Type inference variables appearing in the displayed hover-text for F# values
            F# Library      open_in now opens in ASCII encoding.  Use stream_reader_to_in_channel to open in other encodings

Local names. Improved naming of locals to help during debugging.

Additional Overloading Strings now support overloaded '+'.

Customizable Debugger Views for F# Types. F# types can now be augmented in a a number of ways to customize how the values appear in a debugger. Firstly, the ToString member may be adjusted for each F# concrete type (i.e. record, discriminated union and object types). Secondly, the .NET 2.0 standard DebuggerDisplay attribute can be used in conjunction with member augmentations to customize the simple textual display associated with a type. For example:

type 
 []
 MyIntList =
   | MyNil
   | MyCons of int * MyIntList
 with 
   member x.Length =
      let rec length x acc = match x with MyNil -> acc | MyCons(a,b) -> length b (acc+1) in 
      length x 0
 end

Finally, for sophisticated structured collections the .NET 2.0 standard DebuggerTypeProxy can be used in conjunction with member augmentations to specify a class that represents the visual display of an object. For example:

type 
 []
   MyIntList = MyNil | MyCons of int * MyIntList
and MyIntListDebugView =
   class 
     val v: MyIntList
     new(x) = { v = x }     
     [] 
     member x.Items = 
        let rec length x acc = match x with MyNil -> acc | MyCons(a,b) -> length b (acc+1) in 
        let len = length x.v 0 in 
        let items = Array.zero_create len in 
        let rec go n l = match l with MyNil -> () | MyCons(a,b) -> items.(n) <- a; go (n+1) b in 
        go 0 x.v;
        items
   end

Custom Attribute Extensions Custom attributes now accept 'type' arguments. Double parantheses (to disambiguate the start and finish of the extra argument) and the keyword type must currently be used:

  []

Library additions: Option. The Option module is now a standard part of MLLib. It has a set of functions similar to List.

Library additions: Printf.failwithf and more. The Printf module now supports the failwithf function, which uses structured formatting to print to a string and then raise a Failure exception for this string. The new printer bsprintf is also supported: this prints to a string but intermediary functions print to string buffers. More general compositional forms of Printf operators are also included that let you specify a 'final action' for the printig such as flushing or raising an exception. Finally the OCaml-style 'format4' printer specifications are now also supported - these enable overall return types to be distinct from the types generated by intermediary printers.

Inclusion of a very preliminary release of a top-level command-line interactive environment for F#. The top-level environment will be fsi.exe. This is work in progress, and is included only for testing purposes.

Inclusion of a very preliminary release of FSharp.Compiler.dll, a hostable F# compiler. This is work in progress, and is included only for testing purposes.

Defining Events in F# Events should be defined using new definitions in Microsoft.FSharp.Idioms. For example:

open System.Windows.Forms
open Idioms

type MyCanvas = 
  class 
    inherit Form
    val redrawListeners: EventListeners
    member x.Redraw = x.redrawListeners.Event
    override x.OnPaint(args) = x.redrawListeners.Fire(args)

    new() = { inherit Form(); redrawListeners= new EventListeners() }
  end

let form = new MyCanvas()
do form.Redraw.Add(fun args -> Printf.printf "OnRedraw\n")
do form.Activate()
do Application.Run(form)

Note we are using a property of type Idioms.IEvent<PaintEventArgs> to represent the event. The object returned by this property has Add, AddHandler and RemoveHandler methods (see below). In a future release of the compiler properties of type Idioms.IEvent<PaintEventArgs> will automatically result in appropriate .NET metadata for the event being inserted in the generated assembly. In the current release events defined using this mechanism may still be used from C# and other .NET by using AddHandler and other methods on themediating object.

type Idioms.SimpleEventArgs<'a> = 
  class 
    inherit System.EventArgs 
    member Data: 'a 
    new: 'a -> SimpleEventArgs<'a>
  end

type Idioms.SimpleEventHandler<'a> =  System.EventHandler>

type Idioms.IEvent<'a> = 
   interface 
      inherit IDelegateEvent
      // The inheritance gives:
      //    abstract AddHandler: SimpleEventHandler<'a> -> unit
      //    abstract RemoveHandler: SimpleEventHandler<'a> -> unit 

      // We add this one, which from F# code this is very simple to use:
      abstract Add: ('a -> unit) -> unit
   end

type Idioms.event<'a> = IEvent<'a>

type Idioms.EventListeners<'a> 
  with
    member Fire: 'a -> unit
    member Event: IEvent<'a>
    new: unit -> EventListeners<'a>
  end

Changes between v1.0.8.0 and v1.0.8.6

Renamed fslib10ng.dll to fslib10.dll, since there was a bug with using F# with Visual Studio 2003, and also the "ng" (non-generic) suffix was redundant and clumsy.

Stabilized string hash codes across .NET v1.1 and v2.0. That is, F#'s structural hash function no longer hashes strings by calling String.GetHashCode, since the hash codes returned were different between version 1.1 and 2.0.

Fixed a bug with the debug marks being attached for the entrypoint of executables.

A special function Pervasives.rethrow is now supported. This rethrows the exception for the current "try/with" block. However, it may only be used in catch blocks. Using it in a first class way or outside a catch block will result in a binary that cannot be verified. The correct use of this function is not checked in this version of F# but will be checked in a later version.

Fixed a bug that prevented the generic EventHandler type from being used (or indeed any generic type that was in the same namespace as a non-generic type with an identical name).

F# .EXEs that do not use function values, list types, option values or any other fslib or mllib no longer pick up a dependency on fslib.dll. DLLs incorporating interface data or optimization data still acquire a dependency.

Changes between v1.0.4.3 and v1.0.8.0

Welcome James Margetson to the F# team!

F# now works with Whidbey Beta 2 releases of .NET (EDITOR: the latest releases no longer support Beta 2). F# can continue to be used with .NET 1.0 and 1.1, but can no longer be used with Whidbey Beta 1. If you are still using Whidbey Beta 1 and don't want to upgrade to Whidbey Beta 2 then add --cli-version 1.1 to your compilation switches to compile for .NET 1.1 (likewise 1.0) instead.

Change to Library Naming. The F# libraries fslib and mllib now come in two flavours: one for use with .NET 1.x (no generics) and one for use with .NET 2.0 Beta 2 and beyond (this is to ensure that the library can take advanatage of new features of the platform). The .NET 1.x version of the library has the suffix "10" attached. Thus you will see both fslib.dll and fslib10.dll in this release. F# will automatically reference the correct DLL. When compiling C# code with .NET 1.x you will need to reference fslib10.dll and mllib10.dll.

Rename some internal functions. Some internal functions such as GenericCompare have been renamed appropriately, e.g. to StructuralCompare.

Performance improvements. Language additions. Compiler additions.

Bugs fixed

    351     F# Compiler     Use of invalid format specifier such as %l in a Printf string gives a poor error message
    381     F# Library      input_char cause exception to be thrown
    318     F# Compiler     F# lets two constructors have the same name and gives error when emitting binary
    321     F# Compiler     compiler error reported by Greg Lee
    332     F# Compiler     F# reports error when a "for" variable is used within an inner closure, complaining it is mutable
    333     F# Compiler     Cannot hide exception declarations
    252     F# Perf         fsyacc parser is allocating a lot of list and option nodes
    399     F# Perf         Move generation of comparison and hash methods earlier (to typechecker) so that the code can be fully optimized (and inlined!!)
    281     Abstract IL     implement output of debug symbols for Abstract IL and bootstrapped compiler
    175     F# Tools        Implement error recovery in fsyacc generated parsers

Changes between v1.0.4.0 and v1.0.4.3

Restricted operator overloading to built-in types only for the time being. This is simply an implementation incompleteness.

Added float32 and other float32-related operations to Pervasives.

Changes between v1.0.3.0 and v1.0.4.0

Constrained Type Parameters

F# now allows type parameters to be constrained to specify the minimum functionality the instantiating type must support.

You may be familiar with constrained type parameters from elsewhere. For example, C# and .NET generics support 'subtype' constraints on generic type variables. OCaml supports structural 'object-type' constraints and an additional kind of variable known as a 'row' variable. Standard ML supports a two minor forms of constrained polymorphism in the form of record types (which must be locally resolved) and equality types.

Constrained polymorphism affects both type checking and type inference. In this release, F# supports coercion constraints (on any type variables) and overloaded operator constraints (on pseudo type variables).

Coercion constraints are of the form typar :> type, and also arise from the constructs expr :> type and pattern :> type. For example: