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

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 how to join the F# email list. You may be interested in tracking Don Syme's F# blog and/or blogging about your experiences with using F#.

Contents:

Requirements

Compiler Installation

install-fsharp.bat installs the F# library and the ML compatibility library in the Global Assembly Cache on your machine so you can run the programs you compile from anywhere. It also schedules fsi.exe for .NET pre-compilation. Several flavours of these library may get installed, e.g. for use with early versions of the .NET Common Language Runtime (e.g. fslib10.dll - the '10' stands for 'version 1.0 or version 1.1'). F# will select the appropriate library based on the command line switches you use. You may install the libraries on other machines by copying appropriate files and running the install-fsharp.bat script there.

Installing F# for Microsoft Visual Studio 2003 and 2005

To install and use the 'F# for Microsoft Visual Studio' components, follow the following steps carefully.

1. Run install-fsharp.bat (see Compiler Installation).

2a. If you have Visual Studio 2005 (Beta 2 or later):

2b. If you have Visual Studio 2003:

Troubleshooting installations of F# for Visual Studio

Debugging F# code using Microsoft Visual Studio 2003 and 2005

The Visual Studio Debugger will work with F# code without any additional installation steps. Debugging information for the libraries may be found in the bin directory. In Visual Studio 2005 you may need to disable "Just My Code" debugging (use the "Options" menu). You can also set the appropriate symbol path there or you can add that path to the _NT_SYMBOL_PATH environment variable.

Four ways to write Hello World in F#

Let's write a program in a file main.fs, e.g.

   let _ = print_endline "Hello world"

and the compile and run it using fsc.exe:

   > c:\fsharp\bin\fsc main.fs
   > .\main
   Hello world

or enter it into fsi.exe:

C:\fsharp> bin\fsi

MSR F# Interactive, (c) Microsoft Corporation, All Rights Reserved
F# Version 1.1.3.2, compiling for .NET Framework Version v2.0.50215

> let _ = print_endline "Hello world";;
Hello world

> #q;;

Note the ";;" to terminate entries into fsi.exe.

Now let's write it another way:

   do List.iter (fun s -> print_string s) ["Hello"; " "; "world"]
   do print_newline()

That shows you how to use function values (lambdas) and one function from the list library (nb. do is much the same as let _ = ). List processing is very common and powerful in functional programming. Of course we get the expected result when we run the above program.

Here's still another way, which shows you how to define and use new record and class types with properties and constructors, and also a call to Printf.printf :

   type Data = 
      { first: string;
        second: string; }

   type MyDataWrapper = 
      class 
        val data : Data
        new(data) = { data = data }
        member x.First = x.data.first
        member x.Second = x.data.second
      end

   let myData = 
      new MyDataWrapper({ first="Hello";
                          second="world"; })
 
   open Printf;;
   do printf "%s %s\n" myData.First myData.Second

(Note: of course you could do this all with just one class with two val fields, but then again you could do the whole program in one line :-))

And here's another way, which shows you that you can call the .NET standard libraries instead of the min-functional programming library provided with F#:

   do SystemoConsole.WriteLine("Hello world")

Finally, to write components you will often want to write signature files (.fsi). Here's a very simple interface file:

   test.fsi:
      val double: int -> int
      val four: int

   test.fs:            
      let double x = x + x
      let four = double (double 1)    

Using the F# Compiler

The command line compiler is bin\fsc.exe. The samples give a guide to using the compiler, both alone and in conjunction with other .NET programming tools. Some of the samples require the Microsoft .NET Framework SDK.

Common switches are:

   -a              build a DLL (an archive)
   -g              generate debugging information
   -O3             maximal optimization
   -I              add a path to search for compiled interface files

Files produced include:

   abc.dll         a compiled .NET assembly (use the -a flag)
   abc.exe         a compiled .NET executable
   abc.pdb         Windows debugging information
   abc.ildb        SSCLI debugging information

Using F# Interactive

'F# Interactive' is the name of the top-level command line interpreter for F#. The mode is still under development but ca be used for many tasks and only runs on .NET 2.0 (Visual Studio 2005). Run it using bin\fsi.exe. The TermWalker sample gives an example script you can paste line-by-line into the top-level environment. You can also compile this script file using fsc.exe. Inputs to fsi.exe are terminated with ;; (nothing happens until you type this!)

Common switches are:

   --gui           run a session with a GUI event loop.build a DLL (an archive)
   -O3             run a session that produces maximally optimized code on-the-fly
   -I              add a path to search for compiled interface files
   -r              reference a DLL

Common meta-commands you can enter into fsi.exe are:

#r ;;    dynamically reference the given DLL.
#I ;;    add the given include path.
#use ;;  load the given file.
#time;;          toggle timing on/off.
#quit;;          quit the session.

The first two of these can also be used directly in F# source code files. It can also be useful to quote filenames using 'verbatim strings', e.g.

#r @"c:\fsharp\bin\absil10.dll";;

Finally, F# Interactive currently uses non-generic code, and so any referenced F#-compiled assemblies must have been compiled using --no-generics. It is common practice to suffix such files with 10, as in the example above.

Using the F# Library

F# comes with three libraries.

The source code for fslib.dll and mllib.dll are included as sample code. MLLib gives a standard functional progrmaming library that lets you write code that will cross-compile as both OCaml and F# code. However, you are not committed to using MLLib, as all the primitives required for building your own functional programming library are provided in fslib.dll (use the source code to MLLib as a guide).

All compilations currently implicitly reference both mllib.dll and fslib.dll, though the former can be disabled using the --no-mllib command line option. However, you may also use F# as a 'pure' .NET programming language, without relying on constructs defined in mllib.dll, i.e. F# code need not rely on mllib.dll, since you can program directly against the .NET libraries.

The interface files that define F# Core Library and MLLib can be found in the lib/fslib and lib/mllib directories. The most important files are:

A subset of this library can also be used to help write code that can be compiled using either F# or OCaml. Cross-compilation may require some conditional compilation, for example to build abstractions that account for the differences between F# and OCaml, e.g. the fact that OCaml strings are not Unicode. See the manual for details on how to use conditional-compilation in F#.

Notes

Changes

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 obejct 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 CHsahSet.

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. The binary fscb10ntc 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. 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:

Overloaded operator constraints arise when using overloaded operators +, - etc. For example, the operator + may be used on any two .NET values supporting the overloaded operator op_Addition (written static operator +(...) in C#). (They may also be used on built-in integer and floating point types, which are considered by F# to implicitly define operators such as op_Addition). Overloaded operators are generally only defined within the F# library. Overloaded operator constraints can only be placed on pseudo type variables.

(Aside: pseudo type variables are type variables that occur only within the type checking of a single file. These type variables arise primarily from the use of pseudo-functions such as overloaded operators.)

Examples

In a signature a value declaration may be annoated with constraints. The most primitive way to do this is to use a when annotation on a value declaration. We saw an example of this above. The same declaration can be written using the following more convenient syntactic forms:

    val throw: 'e -> unit when 'e :> System.Exception
    val throw: (_ :> System.Exception) -> unit
    val throw: ('e :> System.Exception) -> unit

As with types, constraints will be inferred from the definition of a method. For example

    open System.IO
    let to_binary_writer s = new BinaryWriter(s)

will infer the type

    val to_binary_writer: (_ :> Stream) -> BinaryWriter

That is, because the constructor for System.IO.BinaryWriter accepts any subtype of System.IO.Stream, F# has also inferred that the derived function should accept any subtype of System.IO.Stream as its argument. You could also write this explicitly using:

    let to_binary_writer (s :> Stream) = new BinaryWriter(s)

Here the pattern (s :> Stream) means 's should match a value whose type can be coerced to Stream'.

Type Inference and Checking

Type inference and checking of constraints is fairly straight-forward: each use of a value or type whose specification involves constrained type parameters will induce a constraint on the actual type parameters associated with the use of that item. (Aside: each time an ML value is used a fresh set of actual type parameters is generated - for example each time you write List.length a fresh inference type parameter is implicitly used as the actual type parameter for the value.)

Constraints are solved, or partially solved, as they are generated. For example:

The following limitations currently apply:

Extensions to the Grammar for Constrained Type Parameters

The extensions to the grammar are as follows:

  <val-type> :=
    | <type>         -- unconstrained type
    | <type> when <constraints> -- constrained type

The following syntactic forms are for convenience. They imply constraints at the binding site related to the type variable (see below).

   <type> :=
    | <typar> :> <type>      -- the same as <typar>, with an implied constraint 
    | <typ> when <constraints> -- constrained type

The constraints can be of the following forms:

  constraint :=
    | <typar> :> <typ>  -- the type parameter converts to the type
    | $<typar>.<method-name> : <method-type>   -- overload constraint

Aside: Binding sites for type variables are inferred in the usual way for ML languages of the OCaml family. This binding site is either a value declaration, a type declaration. Inference variables will be bound at the value declaration where they are generalized, or if not generalized will have the scope of the entire file.

Extensions to the Semantics of Coercion Operators

The operator expr :> typ now means 'expr can be coerced to typ'. This includes the use of representation-changing conversions such as boxing.

Uses of Constrained Polymorphism in the F# Library

Pervasive Operators:

Overloading is supported for the following operators. The operators all default to operating over the int type should there be no other type information in the file to further constrain the use of the operator.

    val (+): $a -> $b -> $a when $a.op_Addition : ($a, $b) -> $a
    val (-): $a -> $b -> $a when $a.op_Subtraction : ($a, $b) -> $a
    val ( * ): $a -> $b -> $a when $a.op_Multiply : ($a, $b) -> $a
    val (/): $a -> $b -> $a when $a.op_Division : ($a, $b) -> $a
    val (mod): $a -> $b -> $a when $a.op_Modulus : ($a, $b) -> $a
    val (~-): $a -> $a when $a.op_UnaryNegation : ($a) -> $a
    val (~+): $a -> $a when $a.op_UnaryPlus : ($a) -> $a
    val (land): $a -> $a -> $a when $a.op_BitwiseAnd : ($a,$a) -> $a
    val (lor): $a -> $a -> $a when $a.op_BitwiseOr : ($a,$a) -> $a
    val (lxor): $a -> $a -> $a when $a.op_ExclusiveOr : ($a,$a) -> $a
    val lnot:  $a -> $a when $a.op_LogicalNot : ($a) -> $a
    val (lsl): $a -> int -> $a when $a.op_LeftShift : ($a,int) -> $a
    val (lsr): $a -> int -> $a when $a.op_RightShift : ($a,int) -> $a
    val (asr): $a -> int -> $a when $a.op_RightShift : ($a,int) -> $a

List, Stream, Vector, Array, Set:

The following functions are for transforming F# collections to and from .NET collections and now accept coerced arguments at F# call-sites:

    List.of_IEnumerable: (_ :> IEnumerable<'a>) -> 'a list
    List.of_ICollection: (_ :> ICollection<'a>) -> 'a list

    Array.of_IEnumerable: (_ :> IEnumerable<'a>) -> 'a[]
    Array.of_ICollection: (_ :> ICollection<'a>) -> 'a[]

    Vector.of_IEnumerable: (_ :> IEnumerable<'a>) -> Vector<'a>
    Vector.of_ICollection: (_ :> ICollection<'a>) -> Vector<'a>

    Stream.of_IEnumerable: (_ :> IEnumerable<'a>) -> Stream<'a>
    Stream.of_ICollection: (_ :> ICollection<'a>) -> Stream<'a>

Idioms:

The following functions now accept coerced arguments at F# call-sites:

    Idioms.foreach: (_ :> IEnumerable) -> ('a -> unit) -> unit
    Idioms.foldeach: (_ :> IEnumerable) -> 'acc -> ('acc -> 'a -> 'acc) -> 'acc

    Idioms.foreachG: (_ :> IEnumerable<'a>) -> ('a -> unit) -> unit
    Idioms.foldeachG: (_ :> IEnumerable<'a>) -> 'acc -> ('acc -> 'a -> 'acc) -> 'acc

    Idioms.using: (_ :> System.IDisposable) -> (unit -> 'a) -> 'a
    Idioms.lock: (_ :> System.Object) -> (unit -> 'a) -> 'a 

The following functions are now checked more strictly.

    Idioms.EnumToInt: 'a -> int             when 'a :> System.Enum
    Idioms.IntToEnum: int -> 'a             when 'a :> System.Enum
    Idioms.CombineEnumFlags: 'a list -> 'a  when 'a :> System.Enum
    Idioms.TestEnumFlag: 'a -> 'a -> bool   when 'a :> System.Enum

Fixed the following bugs:

    282	fsyacc doesn't like // comments
    267	interface data being attached to assemblies includes is bigger than it should be
    286	NGEN of bootstrap compiler fails due to multiple mscorlib references.
    291	bug in the implementation of stable_sort
    292	Compiler bug - cannot find fslib library automatically
    295	--standalone doesn't fold in debug symbols of the assemblies that have been read
    293	install-fsharp.bat gives a spurious error while loking for NGEN
    296	multiple mscorlib references are appearing in --standalone assemblies (fscbng.exe)
    302	VS plugin is not reloading referenced DLLs as they are recompiled (this forced users to restart VS to see changes)
    303	Sys.time is returning Ticks not TotalSeconds
    305	Implementing IEnumerator on .NET v2.0 beta 2 is difficult due to inclusion of parent interfaces with identical method names

Changes between v1.0.1.6 and v1.0.3.0

Fixed a bug related to inner polymorphic closures reported by Nikolaj Bjoerner (thanks Nikolaj!)

Fixed a bug related to over-applied polymorphic functions reported by Dominic Cooney (thanks Dominic!)

Implemented intellisense for further long-name lookups in VS integration, e.g. val.field.field or val.property.field

Fixed the following bugs:

272	Fixed: AV in VS Plugin when endlessly loading & unloading large F# projects
274	Fixed: A failure "stelem" occurred when compiling a test for .NET 2003
247	Fixed: test and document hashq operator
232	Fixed: verify non-generic assemblies using v1.0 and v1.1 peverify's
223	Fixed: Change test procedure to generate config files in order to test on various versions of the clr
275	Give better error messages when passing a value to a Params C# method
276	Give better error message when a CompatArray is needed

Changes between v1.0.1.5 and v1.0.1.6

Added another DirectX Tutorial (Tutorial 1)

Changes between v1.0.1.4 and v1.0.1.5

Fixed installer problems on VS 2003 - Babel package was still being registered with VS 2005

Reduce size of optimization information attached to F# DLLs.

Minor fixes to the Visual Studio installer.

Minor performance improvements for the command line compiler.

Fixed this bug:

268 F# Compiler: not all type definitions were being checked for cyclic abbreviations

Changes between v1.0.1.3 and v1.0.1.4

Fixed one bug with intellisense where extra text on the line after the cursor was interfering with intellisense. Some glitches remain in this area.

Reduced the number of match-bracket calls to improve reponsivity of VS. Some bugs remain in this area.

Minor fixes to the Visual Studio installer.

Performance improvements for the command line compiler.

Fixed minor bugs with the recent additions to MLLib.

Changes between v1.0.0.4 and v1.0.1.2

New reserved keywords after review of keyword policy: atomic, checked, class, decimal, event, pure. In addition the existing reserved word interface is now actually used as a keyword, and will hence give errors if used in your program. The others will give warnings.

Intellisense is now supported in the Visual Studio integration. Essentially all features are complete, though incorrect or slightly misleading information is occasionally be shown, and the correct context is not always available to allow information to be shown. You can turn off Intellisense globally by setting the environment variable FSharp_NoIntellisense=1.

Extended Object Expressions are now supported. This means objects created via object expressions can support multiple interfaces, which also makes F# a CLS Extender language according to the official definition of such things. The syntax is:

   { new  with 
     interface  with 
     ...
     interface  with  }

e.g.

    { new Object()
        with Finalize() = cleanupFunction(false);
        
      interface IDisposable 
        with Dispose() = cleanupFunction(true);  } 

Nested modules within a top-level module are now supported, e.g.

   type ident = Id of string
   module Ident = struct
     let OfString(s) = Id(s) 
     let ToString(Id(s)) = s
   end

and in the interface file

   type ident
   module Ident : sig
     val OfString: string -> ident
     val ToString: ident -> string
   end

The atomicity of dynamic initialization is on the granularity of top-level modules, i.e all the bindings in a top-level module are executed for side-effects if any values in the file are required.

Patterns can now refer to .NET literals.

More .NET related functionality in the ML compatibility library. Modules Float, Float32, UInt32, UInt64, Stream. A much more systematic treatment of conversions between various integer and floating point types. Conversion functions to allow MLLib collections to be used as .NET collections (ICollection etc.). More efficient implementations of some functions.

Visual Studio for .NET will now work with Visual Studio 2003. See the installation instructions elsewhere in this file.

Controlling F# for Visual Studio if it starts to misbehave. The following global environment variables can be used to selectively control some of the features of F# for Visual Studio. They can also be set within the command shell where you execute devenv.exe if you run it explicitly.

      set FSharp_Logging=1
      set FSharp_LoggingVerbose=1
      set FSharp_NoParsing=1
      set FSharp_NoChecking=1
      set FSharp_NoPriorInputParsing=1
      set FSharp_NoConfigBuilding=1
      set FSharp_NoPriorInputTypeChecking=1
      set FSharp_NoTypeChecking=1
      set FSharp_NoLexing=1
      set FSharp_NoIntellisense=1

Documentation:

  -- Revised grammar documentation in manual
  -- Revised interop decumentation in manual

Various bug fixes:

The following bugs were recorded as fixed in the F# bug database:

_	F# Compiler	Implement setting of fields and properties on .NET value types for the simpe cases of mutable locals and byref arguments
196	F# Compiler	Poor error message for signature mismatch when an abbreviation is hidden
211	F# Compiler	too many long paths printed when using -i
204	F# Compiler	fsyacc: newline missing
200	F# Compiler	Newline or similar needed between errors
197	F# Compiler	Can access hidden constructors and fields using long path names
137	F# Compiler	Implement accessing generic methods
210	F# Compiler	--standalone bug for winforms reported on f# list
259	F# Compiler	Fixed a bug with generalizing variables: not all generalized type variables were being marked as rigid
255	F# Compiler	The representation of discriminated unions that uses static fields and unique objects for unary constructors does not work for deserialized data
263	F# Compiler	X-module optimization bug related to incorrectly fixed-up optimization data
183	F# Compiler	Error messages from failed overloading can be poor (e.g. Text3D sample)
187	F# Compiler	Error message when attempting to access a protected method from outside a subclass needs work
218	F# Compiler	Add error when module name  declaration is missing from intf or impl when filenames match e.g a.ml & a.mli
227	F# Compiler	Signature checking of modules should be able to unify inference type variables
242	F# Language	support #else in #if/#endif
194	F# Library	Ensure float32, float etc. and other conversions are all complete and orthogonal in MLLib
249	F# Library	Sys.time not correctly implemented
256	F# Library	Added functions to Set, List and Stream to relate MLLib collections to .NET collections
206	F# Documentation	export interop documentation needs work
212	F# Documentation	Add 'differentiate' and other samples to the sdk
260	F# Documentation	Update docs in parsing sample to reflect the presence of fsyacc and fslex
231	F# Visual Studio Plugin	'UncontrolledError' appears  in error box when using VS
261	F# Release	Visual studio mode fails to install if user has never started up visual studio since installing it

Changes between v1.0.0.2 and v1.0.0.4

Various bug fixes:
  33	26/11/2004	Abstract IL	Generic constraints not correctly read/emitted in binary reader/writer
  157	26/11/2004	F# VS           VS should take into account the include path
  180	02/12/2004	F# Compiler	Private constructors may be visible to importing modules
  185	10/12/2004	F# VS           Problem when loading a F# project where a file did not exist
  193	10/12/2004	F# Compiler	Abstract IL and F# bug: errors when accessing fiels and methods where types have custom attributes
  192	10/12/2004	F# Compiler	upcasting from .NET array types to object reported a bogus warning about boxing,
  191	10/12/2004	F# Compiler	Errors are not reported at right location when argument types are wrong
  186	10/12/2004	F# Language	Cannot access protected methods on .NET objects
  178	19/11/2004	F# Compiler	Declaring a field of a given name blocks out any ability to access members of that name regardless of type annotations
  177	19/11/2004	F# Compiler	Some value recursive declarations incorrectly being labelled as "recursive data"

Changes between v1.0.0.0 and v1.0.0.2

1. New compiler switches:

  --all-warnings: Print all warnings.
  --no-warnings: Do not print any warnings.
  --warn : Report the given specific warning.
  --no-warn : Do not report the given specific warning.
  --all-warnings-as-errors: Treat all warnings as errors.
  --warn-as-error : Treat the given specific warning as an error.

Warning numbers are printed as part of error messages and the less obvious
ones will have further documentation in the manual including links to tutorials.

2. Better and fewer error messages for uses of value recursion.

3. Fixed a number of bugs:
   - Pretty much all uses of data constructors within value recursion declarations were incorrectly
     being labelled as "direct recursion" instead of "value recursion".

   - Field lookup was preferring ML-style field lookup over adhoc-name field lookup based on
     inferred type.  This meant that declaring an F# field such as "Text" anywhere in your
     program meant that no adhoc lookup on "Text" would ever be resolved.

   - Type information was not being propagated correctly from outside-in for "let rec" bindings.

Changes between v0.6.6 and v1.0

1. Change the compilation model to compile assemblies in one shot 
   like C#.  This gets rid of ALL the .cno, .cni, .cnx and .cnw files, 
   leaving just a DLL.  The compiler will add a custom attribute to store 
   the F# interface and optimization data.  For this version this will be 
   brittle under changes to the F# compiler, but we will revisit that in 
   later versions to arrive at a stable metadata format.


2. Cleanup code in preparation for the long-awaited source release.  In particular

  * The parser had several of uppercase/lowercase distinctions left over from my 
    initial version of a parser for the Caml syntax.  These don't apply to F# 
    which disambiguates more identifiers at a later stage.

  * Some optimizations have been rearranged, so less is done in the backend
    phase of the compiler.  This greatly simplifies the code. 

  * The treatment of the decision trees that arise from pattern matching was
    too complex.  This has been simplified.

3. Add more support for making F# code highly usable from C# and other .NET 
   languages.  I have the long term aim to make sure that simply no one can tell 
   something is written in F# if you don't want them to.  The design for this is 
   somewhat up in the air, but will almost certainly involve attributing the F# 
   code to indicate how it should look from C# and other .NET languages.

4. Cleanup namespaces.

   All F# stuff is now in Microsoft.FSharp.

   All built-in types like list, option, ref, etc. will also be defined there.  
   From C# they will be called List, Option, Ref etc.  
     Microsoft.FSharp.MLLib.Pervasives
     Microsoft.FSharp.MLLib.String
     Microsoft.FSharp.MLLib.List
  etc.  This has obvious advantages, and allows for an F#-specific library in
  the future, and perhaps even other libraries and source syntaxes to provide 
  some level of mix-n-match for other functional programming languages.

5. Generate generic code by default.  Non-generic code for 
   use with versions of the CLR prior to Whidbey will need a 
   command line option, e.g. "-no-generics"

6. Revisit subtyping, especially w.r.t. overloading, upcast, downcast etc.

  Casting and nulltest operations for .NET types are now built-in 
  as primitive syntactic forms in F#.  

     expr == 
      | e :? ty      -- dynamically test if 'e' has type 'ty'.  A compile-time error
                        will occur if local type inference does not
                        infer types such that this is a valid downward type test. 
 
      | e :> ty      -- statically upcast 'e' to type 'ty'.  A compile-time error
                        will occur if local type inference does not
                        infer types such that this is a valid upcast. 
 
      | e :?> ty     -- dynamically downcast 'e' to type 'ty'.  A compile-time error
                        will occur if local type inference does not
                        infer types such that this is a valid downcast. 
 
      | downcast e   -- runtime checked downcast from 'e' to an arbitrary type 
                        inferred from the context.  A compile-time error
                        will occur if local type inference does not
                        infer types such that this is a valid downcast. 
 
      | upcast e     -- statically checked upcast from 'e' to an arbitrary type
                        inferred from the context.  A compile-time error
                        will occur if local type inference does not
                        infer types such that this is a valid upcast. 
  
      | e1 ?? e2     -- dynamically test if 'e1' is null, and if so evaluate e2.
                        A compile-time error will occur if local type inference
                        does not infer types such that e1 is a .NET type.  Equivalent to
                           (match e1 with null -> e2 | freshv -> freshv)
 
      | null         -- generate a null value of an arbitrary type inferred
                        from the surrounding context.  A compile-time error
                        will occur if local type inference does not guarantee that
                        the type of the value is definitely a .NET reference type.

    pat ==           
      | null         -- the pattern corresponds to a null test. A compile-time error
                        will occur if local type inference does not ensure that
                        the value being matched against is a .NET reference type.

      | :? ty        -- the pattern corresponds to a .NET type test.  A compile-time error
                        will occur if local type inference does not
                        infer types such that this is a valid downward type test. 

      | :? ty as id  -- the pattern corresponds to a .NET type test, and if 
                        successful the variable 'id' is bound to the value at the given
                        type.

Examples: 

a. Doing a null test in a pattern match:
                   
       let d = new OpenFileDialog() in 
       match d.OpenFile() with 
       | null -> Printf.printf "Ooops... Could not read the file...\n"
       | stream -> ...
            let r = new StreamReader(stream) in 
            Printf.printf "The first line of the file is: %s!\n" (r.ReadLine());

b. Doing a null test in an expression:
                   
       let myReader = new StreamReader(new FileStream("hello.txt")) in 
       while true do Console.WriteLine(myStream.ReadLine() ?? raise End_of_file); done;


Valid casts are those between .NET types related by class extension or interface
inheritance, and also between F# reference types and the type 'obj' (i.e. System.Object).
Thus F# values can be stored in heterogeneous collections such as 
System.Collections.ArrayList.

Local type inference is underspecified in this version of F#. 
In a future version of F#  this will be adjusted to correspond to the 
process of using only "definite" type information in order to make a 
compile-time assessment, i.e. type information from external libraries and modules, from
user type annotations, from uses of F# discriminated unions and F# record labels,
and from other similar type information that arises directly from F# syntactic
forms.  

In this version of F# local type inference applies applies all type information
available to the left of a term, including the use of type equivalences inferred
via Hindley-Milner style unification.  


(TODO) 7. Allow attributes to be declared.  Syntax proposed is "[]"
   in various places.  This is not yet settled and is certainly up for discussion.

8. Typesafe OCaml-style 'printf' is now supported.  See the Printf library module.

9. Object expressions are now supported.  


  9a.  Basic object expressions.

   An object expression declares an implementation and/or extenstion of a class or interface.
   For example, 
              "{new IComparer with Compare(a,b) = if a < b then -1 else if b < a then 1 else 0 }"

   In each example below the "{new ... with ... }" expression generates a new class 
   underneath the hood that implements/extends the given type.  
   Note how little type information you need: the required signatures for OnPaint, 
   Compare, ToString etc. are inferred by looking at the unique virtual method that 
   we must be overriding.  Note too how the anonymous classes close over free variables 
   (e.g. capture the variable "n") behind the scenes.

     open System
     open System.Collections
     open System.Windows.Forms
     let myComparer = {new IComparer with Compare(a,b) = compare a b}
     let myFormattable = {new IFormattable with ToString(fmt,fmtProvider) = ""}

     let myForm title n =
       let res = 
        {new Form() 
         with OnPaint(paintEventArgs) = Printf.printf "OnPaint: n = %d\n" n
         and  OnResize(eventArgs) = Printf.printf "OnResize: n = %d\n" } in
       res.Text <- title;
       res

   You may only override/implement methods in anonymous classes.  You may not declare fields
   or new methods.  To override/iumplement virtual properties you should override the "get_PropertyName" and
   "set_PropertyName" methods that represent the property under-the-hood.  Likewise to override
   virtual events you should override the "add_EventName", "remove_EventName" and "fire_EventName"
   methods that represent the event under-the-hood.

 
 9b. Accessing "this" in object expressions.

   There is no "this" keyword, and for good reasons: 
     1. In object-oriented languages an object may not be sucessfully constructed 
        at many points where "this" can be used.  These leads to inherent weaknesses
        in the initialization-soundness guarantees of these languages.

     2. The natural typing for "this"/"self" would reveal the anonymous type
        of the implementation.  Object expressions are for defining implementations, 
        not types, and it is not desireable to mix type-generation with object expressions
        unnecessarily.  This is similar to the way the discriminants of discriminated
        unions are not types in F# (though they may be types in the underlying IL).   

     3. Sometimes you want to access not "this"/"self" but another object in a self-referential 
        graph of objects.  There is nothing fundamentally different between doing that
        and accessing "this" or "self".
 

   However, you can access "this" by using the "reactive recursion" feature described elsewhere in these
   notes.  This feature results in a compiler warning that the initialization guaranteed for the object
   expression may not be as strong as you wish, and in particular that (in theory) the constructor
   for the object may invoke a virtual method which uses "this" before the object is initialized.  For
   example

       let rec obj = {new System.Object() 
                      with GetHashCode() = (obj.ToString()).Length}

   Here the identifier "obj" plays the role of "self" or "this".  This example makes it plainer
   why "let rec" must be used: obj is certainly defined in terms of itself, i.e. its definition is
   self-referential or recursive.

   Note that mutually-self-referential objects can be defined via the same mechanism:

       let rec obj1 = {new System.Object() 
                       with GetHashCode() = (obj2.ToString()).Length}

       and     obj2 = {new System.Object() 
                       with GetHashCode() = (obj1.ToString()).Length}

   Thus the primitive is self-referentiality via "reactive recursion" rather than allowing all
   object expressions to access "this".

  9c.  How to access the base class members, e.g. C#'s base.OnPaint()

   An inescapable part of the design of .NET object-oriented libraries is that they
   require extensions of some class types to use the implementations of overriden methods
   as part of the definition of the extension.   This is seen in C#'s "base" identifier.

   F#'s permits object expressions that extend classes to be defined partly in terms 
   of the base functionality of that class.  This is done be labelling that functionality 
   as part of the object expression:

        {new Form() as base
         with ... }

   Here "base" is not a keyword, just as "this" and/or "self" are not keywords.  Any identifier
   can be used for base, and if object expressions are nested then different identifiers
   should be used at different points.

   In the example, the variable "base" has type "Form", and can only be used to perform
   method invocations, e.g. as follows:

     let myForm =
        {new Form() as base
         with OnPaint(args) = base.OnPaint(args);  Printf.printf "OnPaint\n" n
         and  OnResize(args) = base.OnResize(args); Printf.printf "OnResize\n" n } 


 9d. Implementing multiple interfaces

  This is not supported in this release.



10. Allow F# exceptions to be mapped to/from .NET exceptions, especially
    in cases like Out_of_memory and Stack_overflow.

11. Further optimizations:

  - Standard functional language optimizations for expressions known to be 
    strings, constructors and tuples
  - Lift additional closed expressions to the top level
  - Optimize away inner polymorphism when functions are only used at one type

13. Extensive testing for all optimizations (a number of bugs were fixed 
    which meant optimizations weren't always firing.)

14. Fix a bunch of minor bugs
* Too much stuff was being made public.  This was hurting abstraction and interop.
* Precedence bug with infix operators such as "&&&&" and "||"
* Improved various error messages
* Minor stuff with calling methods on structs
* A bug with Flush on StreamWriters reported by Dominic Cooney (thanks Dominic!)
* Some bugs with error reporting reported by Alain Frisch (thanks Alain!)
* A bug meant that we weren't turning tailcalls into loops for recursive public functions
* A bug meant that an obscure internal error such as "undefined type variable: 'a567" was sometimes being reported.  Appears to be the same as a bug reported by Dominic Cooney (thanks Dominic!)
* Robert Pickering reported various bugs, including one involving delegates (thanks Robert!)
* Creation of delegates taking no arguments (e.g. ThreadStart) had a bug 
* Fixed a typechecker bug with indexer properties
* A couple of error messages weren't being printed, resulting in messages such as 'Tc.Fields_from_different_types(_, _, _)'
* Fixed a couple of bugs with parsing floating point numbers
* int_of_float now truncates the floating point number toward zero, rather than
  rounding.  This is in line with the OCaml specification.  While it's not
  clear that this is the desired behaviour, it seems appropriate that the
  items in Pervasives should follow the semantics of OCaml as closely as possible.
* Fixed many bugs associated with F# values accessed using long paths, e.g. 
  Microsoft.FSharp.Some("3") is a valid way to refer to Some("3").
* The number of compiler generated names appearing in the output has been reduced, and the
  internally generated identifiers that are produced have been made simpler, with fewer
  numbers appearing.
* Can now reference multi-module assemblies. 
* Fixed a bug with the shift operators reported by Dominic Cooney (thanks Dominic!)
* Fixed a bug with the ConcurrentLife sample's repainting behaviour reported by Dominic Cooney (thanks Dominic!)


15. Support 64-bit, 16-bit, 8-bit constants, and unsigned versions of the same,
    62y: 8-bit signed byte
    62uy: 8-bit unsigned byte
    62s: 16-bit signed
    62us: 16-bit unsigned
    62l: 32-bit signed
    62ul: 32-bit unsigned
    62L: 64-bit signed
    62UL: 64-bit unsigned 

   The use of 'l' is a little unfortunate for 32-bit integers, since in C/C++-land
   it means "long", i.e. 64-bit.  However the above is consistent with OCaml's
   use of constants, and there is no point being needlessly inconsistent.

    Literals of type 'bytearray' are now supported, with syntax B"abc\n" etc.
    Literals with syntax "abc\n" are unicode strings as previously.

    Literals of type 'byte' are now supported, with syntax B'\n', B'0', B'\t', B'a', B'\212' etc.
    Literals with syntax '\n', '0', '\t', 'a' '\212' etc. are unicode characters as 
    previously.

16. Greatly improve debug support by getting more accurate sequence points.

17. Unicode escape sequences in identifiers and strings, ala C# style, i.e. \uXXXX and \UXXXXXXXX
    Somewhat crude support for authoring files in UTF-8 encoding is also supported.
    Unicode UTF-8 input may be used, where unicode characters are only currently allowed to appear in strings.
    Unicode characters in identifiers will also currently parse, but no true support is offered here: in particular
    error messages will be garbled, and we do not restrict identifier characters to the expected set of
    alpha-numeric equivalent characters.

18. Support for commercially use by permitting deployment of the F# library if it
    is statically linked into an application. 

    The --standalone switch statically links the F# library and all referenced DLLs
    that depend on that library into the assembly (normally a .EXE) being produced.
    A verbatim copy is made of all the types and other definitions in all these
    DLLs and the copy is added to the assembly produced.  Although these types
    may have the same name as the original types in the C# library, they are 
    logically distinct.

19. Operators.  The following operators have always been supported by F#, but are now
    user definable, rather than being tied to arrays and unicode strings.  
       .[]  .()   .[]:=   .():=    

    This can help with porting OCaml code to F#, since the operations .[] and .[]:= 
    can now be redefined to act on bytearrays rather than unicode strings.
    e.g. 
        let (.[]) s n = Bytearray.get s n
        let (.[]<-) s n m = Bytearray.set s n m
        let (.()) s n = Microsoft.FSharp.Compatibility.CompatArray.get s n
        let (.()<-) s n = Microsoft.FSharp.Compatibility.CompatArray.set s n

   The operators ~- and ~-. have always been available in OCaml but not previously in F#.
   These let you redefine the unary "-" and "-." operators respectively, e.g. 
        let (~-) n = Int64.neg n

20. Accessing .NET: Indexer properties.  Indexer properties can now be accessed with the following
    natural syntax:
      let s = "abcdef" in 
      s.Chars(2)  // returns 'c'

    and for properties with C# syntax 'x[n]' use:

      x.Item(n)

    e.g

       open System.Collections;
       let f (x:ArrayList) = x.Item(0)

21. F#'s version of  "recursion through data types using 'let rec'" 
    to create "infinite" (i.e. self-referential) data structures is now slightly 
    more restricted.  You can't use recursive 'let rec' bindings through immutable fields 
    except in the assembly where the type is  declared.  This means

       let rec x = 1 :: x

    is not supported.  This was required to make sure the head/tail fields of lists are
    marked "private" and "initonly" in the underlying assembly, which is ultimately more
    important than supporting all variations on this rarely-used feature.  However note that

       type node = { x: int; y: node}
       let rec myInfiniteNode = {x=1;y=myInfiniteNode} 

    is still supported since the "let rec" occurs in the same assembly as the type definition,
    and

       type node = node ref
       let rec myInfiniteNode = { contents = myInfiniteNode } 

    is supported since "contents" is a mutable field of the type "ref".


22. Nice-Compiled-Forms: Access of discriminated unions from other .NET languges has been improved.

    F# data types are compiled to C# classes with additional support to access the information carried by
    the data type.

    Constructing values of F# discriminated unions
    ----------------------------------------------

    A static method is supported for each discriminant, e.g.
           List.Cons(3,null)
           Option.Some(3)

    Discriminating on F# discriminated unions
    -----------------------------------------

    The following section applies if the type has more than one discriminant.

    The support depends very marginally on when "null" is used by the F# compiler as 
    a possible representation of value of the data type.  This is because types where "null" is used as
    representation cannot support some instance members (they would result in a null pointer exception
    when used from C#).

    "null" will ONLY be used by the F# compiler in EXACTLY the following situations:
       - For the single value of the "unit" type
       - For discriminated unions with exactly 2 constructors, where exactly one of
         those constructors is nullary - of course 'null' is then used for
         as the representation for the nullary constructor. Thus "null" may be 
         used for the "list" and "option" types, and types very similar to these,
         but will rarely be used for other datatypes.

    If "null" is NOT used as representation then a type will support
       (a) a Tag property and several tag_... compile-time constants.  These can be used for discrimination
           by switching.
       (b) a series of IsXYZ() instance methods, one for each constructor.  These can be used for discrimination
           by predicates.

    If "null" IS used as representation then a type will support
       (a) a GetTag() static method, and several tag_... compile-time constants.  These can be used for switching
    In the latter case discrimination by predicates can be performed by comparing values to "null",
    since the null value is then guaranteed to be used for the single nullary constructor of the type.

    Thus if the C# value x has type MyType and the F# definition of MyType is:
         type MyType = A of ... | B of ... | C of ...

    then the following C# code is valid:

      Console.WriteLine("{0}", x.IsA());
      Console.WriteLine("{0}", x.IsB());
      switch (x.Tag) 
      {
          case MyType.tag_A: 
              Console.WriteLine("A");
              break;
          case MyType.tag_B: 
              Console.WriteLine("B");
              break;
          default:
              Console.WriteLine("Must be a C");
              break;
      }
       

23. Nice-Compiled-Forms: Names for tuple types have changed

   The compiled form of tuple type names and tuple member names has been improved, e.g.
         Tuple<_,_>.Item1
         Tuple<_,_>.Item2

         Tuple<_._,_>.Item1
         Tuple<_._,_>.Item2
         Tuple<_._,_>.Item3

         Tuple<_._,_,_>.Item1
         Tuple<_._,_,_>.Item2
         Tuple<_._,_,_>.Item3
         Tuple<_._,_,_>.Item4

         ... 

         Tuple<_._,_,_,_,_,_>.Item1
         ...
         Tuple<_._,_,_,_,_,_>.Item7

    The compiled forms for tuples of size > 7 are under-specified.  The above names change slightly
    when targetting .NET 1.0 or 1.1, i.e. a non-Whidbey release, because we then can't use the arity
    of the generic type to disambiguate the various "Tuple" names.  So the names become
    Tuple2, Tuple3 etc. to Tuple7.

24. Nice-Compiled-Forms: Data fields compiled as properties, not fields

    Properties are now used to compile all memebers of F# record types, i.e. 
         type recd = { Name: string; Size: int }
    will support
         recd.Name  (a property, not a field)
         recd.Size  (a property, not a field)

25. Nice-Compiled-Forms: Fields of alternatives can have names.

    F# discriminated unions can now have named fields, e.g.

         type 'a list = 
             Nil
           | Cons of { Head: 'a; Tail: 'a list } 

     Currently this information is ONLY present for describing the .NET view of such a type.
     The use of such a name leads to the creation of a .NET property with the given name.

     Thus there are strict limitations:
       - The names may not currently be repeated amongst different alternatives.
       - These fields may not be selected from F# code
       - Pattern matching against this form is not yet supported.  
       - That is, for all other purposes the declaration is treated as 
         if the fields were declared sequentially as normal, i.e.

           | Cons of 'a * 'a list

      These restictions may be lifted in a future release.
      The inbuilt list and option types are treated as if they have this form, i.e.

         type 'a list = 
             Nil
           | Cons of { Head: 'a; Tail: 'a list } 

         type 'a option = 
             None
           | Some of { Item: 'a }

     and thus C# code can use

      List x = List.Cons(3,(List.Nil));

      Console.WriteLine("x.Head = {0}", x.Head);
      Console.WriteLine("x.Tail = {0}", x.Tail);
      Console.WriteLine("x.Tail - IsNil = {0}", x.Tail);


26.  (This section only applies when targeting a CLR that supports generics, i.e. when the 
      --no-generics switch is NOT used. )
 
     The compiled form of function types has been finalized to be Microsoft.FSharp.FastFunc<A,B>.  This
     will not change, though the details of the implementation of the 
     Microsoft.FSharp.FastFunc class may be revised.  FastFunc<A,B> is not a 
     delegate type (which may be what some users expect).  This option has been finally rejected
     for both interoperability and performance grounds.  

     Creating function values that accept one argument
     -------------------------------------------------

     It it important to be able to create and use values of this type from C# in a
     fashion that is as easy and natural as possible. 

     One option is to create function values by using subclasses of 
     Microsoft.FSharp.FastFunc that override the "Invoke" method.  However this
     is not the recommended way of creating such values, since it is then not so easy to 
     use C#'s anonymous delegate feature when creating delegates.  

     The most uniform way to create a FastFunc is to use an anonymous delegate.  You simply 
     create an appropriate .NET function-like delegate (e.g. System.Converter) and then 
     call Microsoft.FSharp.FuncConvert.ToFastFunc.  In particular, 
     FuncConvert.ToFastFunc(...) supports the following overloads:

           ...(System.Converter f)  producing  FastFunc 
           ...(System.Action f)       producing  FastFunc 
           ...(System.Predicate f)    producing  FastFunc 

     Additionally, there is an implicit conversion from System.Converter to FastFunc,
     and thus you can omit the call to FuncConvert.ToFastFunc() but ONLY when reating a delegate
     of type System.Converter (for some A,B).

     For example, the following are equivalent:
         List.map(FuncConvert.ToFastFunc((Converter) delegate(int x) 
                                                         { return x.ToString() + x.ToString(); }),
                              myList);

     and 
         List.map((Converter) delegate(int x) 
                                   { return x.ToString() + x.ToString(); },
                              myList);

     Creating curried function values that accept multiple arguments
     ---------------------------------------------------------------

     The above techniques works well when creating F# function values that expect one argument.  
     However the above can be awkward when creating F# function values that accept multiple
     values, whether by "currying" or by "tupling".  Thus the F# library defines
     additional similar types in order to support additional conversions.  In particular it defines

         delegate void System.Action(A1 x, A2 y);
         delegate void System.Action(A1 x, A2 y,A3 z);
         delegate B System.Converter(A1 x, A2 y,A3 z);

     and Microsoft.FSharp.FuncConvert.ToFastFunc(...) method supports
     the following overloads that produce "curried" functions:

       ToFastFunc(System.Converter f)       producing  'A1 -> B',             i.e. FastFunc 
       ToFastFunc(System.Converter f)    producing  'A1 -> A2 -> B',       i.e. FastFunc> 
       ToFastFunc(System.Converter f) producing  'A1 -> A2 -> A3 -> B', i.e. FastFunc> >

       ToFastFunc(System.Action f)            producing  'A1 -> unit',             i.e. FastFunc
       ToFastFunc(System.Action f)         producing  'A1 -> A2 -> unit',       i.e. FastFunc>
       ToFastFunc(System.Action f)      producing  'A1 -> A2 -> A3 -> unit', i.e. FastFunc>>

     For example:

      using System;
      using Microsoft.FSharp;
      using Microsoft.FSharp.MLLib;

      List myList = List.of_array(new int[] { 4, 5, 6 });

      string joined = 
        List.fold_right
          (FuncConvert.ToFastFunc((Converter) delegate(int i,string acc) 
                                    { return i.ToString() + "-" + acc; }),
           myList, 
           "");



     Creating function values that accept multiple arguments as tuples
     -----------------------------------------------------------------

     To create F# function values that accept their arguments as tuples use
     Microsoft.FSharp.FuncConvert.ToTupledFunc.

       ToTupledFastFunc(System.Converter f)       producing  'A1 -> B',           i.e. FastFunc 
       ToTupledFastFunc(System.Converter f)    producing  'A1 * A2 -> B',      i.e. FastFunc> 
       ToTupledFastFunc(System.Converter f) producing  'A1 * A2 * A3 -> B', i.e. FastFunc> >

       ToTupledFastFunc(System.Action f)            producing  'A1 -> unit',           i.e. FastFunc
       ToTupledFastFunc(System.Action f)         producing  'A1 * A2 -> unit',      i.e. FastFunc>
       ToTupledFastFunc(System.Action f)      producing  'A1 * A2 * A3 -> unit', i.e. FastFunc>>


27. Added List.of_array and List.to_array.

28.  Initialization semantics for toplevel bindings have been changed to be
     more suitable for a multi-language, dynamic loading setting.
        -  .EXEs:  The only top-level bindings that are immediately evaluated on startup are those
           in the last module specified on the command line when building a .EXE.  

        -  .DLLs: All bindings in a DLL are executed on demand, at most once each time a module is loaded into
           a .NET application domain.  The execution may be triggered by the access of any of 
           the fields or methods of a module.  The granularity is guaranteed to imply that all the 
           top level bindings in a single F# source file are evaluated sequentially if 
           any are evaluated.  

29.  The compiled type name for the type of hashtables is now 
         Microsoft.FSharp.MLLib.Hashtbl.Hashtbl
     rather than 
         Microsoft.FSharp.MLLib.Hashtbl.t
     This looks better in the debugger and from other .NET langauges.
     The latter (or equivalently Hashtbl.t) is still valid from F# code, and 
     is a F# synonym for the former.  In the future the compiled name of the type may
     be changed to be simply Microsoft.FSharp.MLLib.Hashtbl.
   
     The same applies to Lazy.t

30.  The Buffer module has been implemented in MLLib and is a trivial wrapper for ML's Buffer.t 
     type to .NET'd StringBuilder type.


31. Type operations

     The expression "e :? ty" is equivalent to a dynamic type test.  A warning
     will be emitted if the type of e cannot be statically determined to be
     a subtype of ty (statically determined == using the inference
     information available at this point in the typechecking of the program, where
     inference proceeds left-to-right through the program).  An error will
     be reported if the type test will always succeed.

     This is especially useful for testing for classes of .NET exceptions, e.g. 

      try  
          ... 
      with
       | e when (e :? System.Net.Sockets.SocketException) -> ...
       | e when (e :? System.OutOfMemory) -> ...

     The expression "e as ty" is equivalent to an upcast.  An error
     is given if the compiler cannot statically

32.  Subsumption can now be used at method call sites where this disambiguates 
     a method overload.

That is, upcasts will now be allowed for arguments when calling .NET methods.  The rule for
resolving overloading will be:
o	we only consider overrides that match by name and arity (since we always know the
number of arguments being applied)
o	if there is only one such method then each actual/formal argument must either
match by an upcast or by unification
o	if there are multiple such methods then:
-	if the argument types of only one such method match by type equivalence then that one is used
-	otherwise if the argument types of only one such method match by type equivalence
and/or upcasts then that one is used
-	otherwise report an error

Here upcasts and type equivalence are performed in the sense of "local type inference"
as described below.  Thus the overload resolution is less aggressive than
C# (no automatic boxing/implicit-conversions, less aggressive resolution of ambiguity
between methods based on "best overload") but you can always specify the overload you want.


33. Runtime-checked reactive 'let rec' recursion is now supported.

   This means you can write values (and not just functions) whose
   specifications appear to refer to themselves, but where the
   self-references are hidden inside delayed values such as inner functions,
   other recursive functions, anonymous 'fun' lambdas, lazy computations,
   and the 'methods' of object-implementation expressions.  A much
   broader class of expressions can now be used in 'let rec' bindings,
   and in particular the expressions can be applications, method calls,
   constructor invocations and other computations.

   The recursion is 'runtime checked' because there is a possibility that
   the computations involved in evaluating the bindings may actually take
   the delayed computations and execute them.  The F# compiler gives
   a warning for 'let rec' bindings that may be ill-founded (i.e. bindings which
   it can't convince itself are well-founded), and inserts
   delays and thunks so that if runtime self-reference does occur then
   an exception will be raised.  In the future the exception raised will
   be augmented to carry useful information such as line numbers and
   the dependencies in the bindings.
   
   The recursion is 'reactive' because it only really makes because
   it really only makes sense to use this when defining automaton such
   as forms, controls and services that respond to various inputs
   and make self-referential modifications as a result, e.g. GUI
   elements that store and retrieve the state of the GUI elements
   as part of their specification.  A simple example is the following
   menu item, which prints out part of its state as part of its action:

let rec menuItem : MenuItem = 
  new MenuItem("&Say Hello", 
               new EventHandler(fun sender e ->
                    Printf.printf "Hello! Text = %s\n" menuItem.Text), 
               Shortcut.CtrlH)

A compiler warning is given when compiling this code because
in theory the "new MenuItem" constructor could evalute the callback
as part of the construction process, in which case a self-reference
would have occured - and F# can't prove this won't happen.  It is an
current research topic in the language design community to
design type systems to catch these cases, but in the context of
.NET a relatively non-restrictive construct is needed since stateful
components are unavoidable, and it would be difficult (if not impossible)
to design libraries such as WinForms in such a way that a type system
would prove the well-foundedness of the self-referential accesses.



34. Additional syntax forms supported:
      expr :=  ...
            |  try  finally  -- always execute an exit block, even if an exception occurs

      topdecl := ...
            | module    -- specify the namespace/class for the generated bindings
            | do                   -- execute the given expression

      bindings := ...
            | do                   -- execute a statement as part of a recursive binding

35. New keywords

  For .ML, .MLI, .FS and .FSI files:  finally, upcast, downcast, null, :>, :?>, :?

  Reserved for .FS and .FSI files:
      base   constraint   default   namespace   return   switch   
      enum   extern  fixed   functor   include   inherit   module
      object   virtual  sig   using   interface   class  volatile
      process   method   


36.  Namespaces and module names can be specified with an initial
     declaration at the head of a file, e.g.

         module Microsoft.FSharp.MLLib.Pervasives
         module MyLibrary.MyModule

     The final identifier is treated as the module name, the former
     identifiers as the namespace.

     By default there is no namespace and the existing rule is used
     for the module name (i.e. the first letter of the filename is
     capitalized).  A default namespace can be specified via the --namespace
     command line option.  If any module ddeclaration is given it overrides
     both the default namespace and the rule for naming modules.

37. 'try-finally' blocks are supported

38. The Game of Life sample has been thoroughly revised
    to be a Multi-threaded GUI application showing how
    to control the progress of underlying computations as
    they execute.

39.  C#/C++-style "//" comments-to-end-of-line are now supported.
     "(*" and "*)" have no special meaning inside this comment text.

     This is technically an incompatibility with OCaml code, however it
     is usually trivial to simply change the name of the "//" operator
     to something else.


40.  An extra compiler switch --minimal-cli-version is supported by
     which you can specify the minimal .NET CLI required to run
     the generated binary.  For example, even if you are developing
     using v2.0 (Whidbey) you can generate a bnary for use on V1.1
     by using a combination of "--minimal-cli-version 1.1.4322" and
     "--no-generics", likewise "--minimal-cli-version 1.0.3705".

     The generated binary may, of course, still require library
     features from later versions.  You should certainly run peverify
     from the appropriate version of the .NET SDK on the binaries to
     ensure they are correct.

     As an alterntaive to all of this you may also alternatively
     be able use a configuration file for fsc.exe to ensure
     the correct runtime is used when compiling - see examples such
     as ilasm.exe.config in your
     C:\WINDOWS\Microsoft.NET directory.

41.  F# now supports C#-style #if/#endif conditional compilation.  The
     command line switch is --define.  The conditional compilation syntax to 
     support mixed OCaml/F# programming has also changed a little (the old syntax
     was universally regarded as gross and was non-uniform).  The syntax how is simply
     that text surrounded by 
         (*IF-FSHARP  ... ENDIF-FSHARP*)
     and (*F#         ... F#*)

     are included when compiling with the F# compiler, and  text surrounded by

         (*IF-CAML*)  ...  (*ENDIF-CAML*)
         (*IF-OCAML*)  ... (*ENDIF-OCAML*)

    is excluded when compiling with the F# compiler.  Of course the converse holds when 
    compiling programs using the OCaml compiler.
    


42.  F# now supports generation of retargetable .NET binaries.  Retargetable binaries
     are neutral w.r.t. the publisher of particular referenced binaries.  For example, 
     a truly portable .NET program will be neutral w.r.t. the publisher of mscorlib - 
     rather than picking up a dependency against the publisher of mscorlib used at 
     compile-time. This means the program will bind to ANY assembly called "mscorlib",
     which is OK for mscorlib but is not necessarily such a good idea for other strong
     named assemblies.  

     You can tell if you have generated retargetable references by using the ILDASM
     tool that comes with the CLR.  If you have you will see:

.assembly extern retargetable mscorlib
{
  .publickeytoken = (96 9D B8 05 3D 33 22 AC )                         // ....=3".
  .ver 2:0:3600:0
}
.assembly extern retargetable System
{
  .publickeytoken = (96 9D B8 05 3D 33 22 AC )                         // ....=3".
  .ver 2:0:3600:0
}

     and so on.  Public key tokens are used to help name a referenced assemblies.
     The particular public key token used above is the unique "neutral" key token as
     specified by the .NET ECMA spec.

     I have been told that Microsoft's Compact Framework (CF) counts as a second set of "published" assemblies,
     and so if you want to make binaries that can be executed on the CF and other versions of the
     CLR then you should use this option.
     The --retargetable option is used to indicate a particular assembly reference to 
     make retargetable in the produced binary.  There is no way to make all assembly references
     retargetable - you have to do it on a case-by-case basis.  Furthermore the reference
     to "fslib" is not retargetable, since you have to use the fslib provided in the F#
     distribution.


43.  F# now supports funcitons Map.Make and Set.Make that accept comparison functions and
     return record expressions that act as components.  These are akin to
     OCaml's Set.Make and Map.Make functors.  The release also includes Map,
     Set and Hashtbl implementations that use polymorphic comparison.  Hashtbl.Make is
     yet to be done.

44.  F# now supports "forall" types on fields. That is, fields can have types that logically
     speaking correspond to generic methods.  This is useful when records are used to
     represent modules, e.g. with Map.Make and Set.Make's fold functions.


45.  F# field names may now be used as part of the "." notation even when the field names
     have not been brought into the top level scope via an "open".  For example if
     a module contains
           type recd = { Name: string }
     then you may use
           x.Name
     if x is determined by local type inference to be of type "r".  This is subject to the
     same rules as .NET member lookups, i.e. the type of the value to the left of the "."
     must be determined by local type inference using annotations and other
     information available left-to-right, outside-to-inside.

46.  Optimization improvements to "==" and polymorphic comparison.

47.  A Visual Studio integration is now supported, with syntax
     highlighting, automatic parsing, automatic typechecking 
     and a simple project system.
      
48.  --target-winexe, --target-exe and --target-dll are now supported.

49.  Pervasives now supports string-named versions of all the Caml-style
     operators defined in that file, e.g. op_GenericEquality for '='.  See
     pervasives.fsi for the full list of names used.

50.  A lexer generator along the lines of ocamllex/mosmllex is now supported.  
     Input files identical to ocamllex files are supported, with the following exceptions:
       - using 'as' to label internal portions of matched strings is not supported
       - '#' regular expressions are not supported
       - 'shortest' matching is not supported
       - Command line options -o, -ml, -q are not supported

     The Lexing library module is supported with a specification similar to the specification
     of OCaml's Lexing module.  This was coded from scratch.  Most of the fields 
     of the lexing state are hidden, adn thus differ from OCaml, with the exception 
     of Lexing.lex_start_p and Lexing.lex_curr_p.

51.  A parser generator along the lines of ocamlyacc/mosmlyacc is now supported.  
     Input files identical to ocamlyacc files are supported.  See the notes in the Parsing
     module in MLLib for some compatibility issues.

Changes between v0.6.5 and v0.6.6

Changes between v0.6.4 and v0.6.5