Chapter 10. Using the F# and .NET Libraries

F# and the .NET Framework offer a rich set of libraries for functional and imperative programming. This chapter steps back and gives you a broader overview of the.NET and F# libraries.

Many of the types and namespaces described here are also covered elsewhere in this book. In these cases, we reference the relevant chapter.

A High-Level Overview

One way to get a quick overview of the .NET Framework and the F# library is to look at the primary DLLs and namespaces contained in them. Recall from Chapters 2 and 7 that DLLs correspond to the physical organization of libraries and that namespaces and types give the logical organization of a naming hierarchy. Let's look at the physical organization first. The types and functions covered in this chapter are drawn from the DLLs in Table 10-1.

Table 10.1. DLLs Containing the Library Constructs Referred to in This Chapter

DLL Name

Notes

mscorlib.dll

Minimal system constructs, including the types in the System namespace.

System.dll

Additional commonly used constructs in namespaces such as System and System.Text.

System.Xml.dll

See the corresponding namespace in Table 10-2.

System.Data.dll

See the corresponding namespace in Table 10-2.

System.Drawing.dll

See the corresponding namespace in Table 10-2.

System.Web.dll

See the corresponding namespace in Table 10-2.

System.Windows.Forms.dll

See the corresponding namespace in Table 10-2.

System.Core.dll

The foundation types for LINQ and some other useful types. From .NET 3.5 onward.

WindowsBase.dll

Core functionality for Windows Presentation Foundation.

PresentationCore.dll

Core functionality for Windows Presentation Foundation.

PresentationFramework.dll

Core functionality for Windows Presentation Foundation.

FSharp.Core.dll

Minimal constructs for F# assemblies.

To reference additional DLLs, you can embed a reference directly into your source code. For example:

#I @"C:Program FilesReference AssembliesMicrosoftFrameworkv3.5";;
#r "System.Core.dll";;

The first line specifies an include path, the equivalent of the -I command-line option for the F# compiler. The second line specifies a DLL reference, the equivalent of the -r command-line option. Chapter 7 described these. If you're using Visual Studio, you can adjust the project property settings for your project.

Note

Hundreds of high-quality frameworks and libraries are available for .NET, and more are appearing all the time. For space reasons, this chapter covers only the .NET libraries and frameworks listed in Table 10-1. The "Some Other .NET Libraries" section of this chapter lists some libraries you may find interesting.

Namespaces from the .NET Framework

Table 10-2 shows the primary namespaces in .NET Framework DLLs from Table 10-1. In some cases, parts of these libraries are covered elsewhere in this book; the table notes these cases. For example, Chapter 4 introduced portions of the .NET I/O library from the System.IO namespace.

Table 10.2. Namespaces in the DLLs from Table 10-1, with MSDN Descriptions

Namespace

Description

System

Types and methods that define commonly used value and reference data types, events and event handlers, interfaces, attributes, and processing exceptions, supporting data-type conversions, mathematics, application environment management, and runtime supervision of managed and unmanaged applications. See Chapter 3 for many of the basic types in this namespace.

System.CodeDom

Types that can be used to represent the elements and structure of a source code document. Not covered in this book.

System.Collections

Types that define various nongeneric collections of objects, such as lists, queues, and bit arrays. Partially covered in the section "Using Further F# and .NET Data Structures" later in this chapter.

System.Collections.Generic

Types that define generic collections. See Chapter4 and the section "Using Further F# and .NET Data Structures" later in this chapter.

System.ComponentModel

Types that are used to implement the runtime and design-time behavior of components and controls. See Chapter 11.

System.Configuration

Types that provide the programming model for handling configuration data. See Chapter 15.

System.Data

Types that represent the ADO.NET database access architecture. See Chapter 15.

System.Diagnostics

Types that allow you to interact with system processes, event logs, and performance counters. See Chapter 18.

System.Drawing

Types that allow access to GDI+ basic graphics functionality. More advanced functionality is provided in the System.Drawing.Drawing2D, System.Drawing.Imaging, and System.Drawing.Text namespaces. See Chapter 11.

System.Globalization

Types that define culture-related information, including the language, the country/region, the calendars in use, the format patterns for dates, the currency, the numbers, and the sort order for strings. Not covered in this book.

System.IO

Types that allow reading and writing files and data streams, as well as types that provide basic file and directory support. See Chapter 4 for a basic overview.

System.Media

Types for playing and accessing sounds and other media formats. Not covered in this book. .NET 3.0 and later.

System.Net

Types to programmatically access many of the protocols used on modern networks. See Chapters 2 and 14 for examples and a basic overview.

System.Reflection

Types that retrieve information about assemblies, modules, members, parameters, and other entities in managed code. See Chapter 9 fwor a brief overview.

System.Reflection.Emit

Types for generating .NET code dynamically at runtime.

System.Resources

Types that let you create, store, and manage various culture-specific resources used in an application. See Chapters 7 and 11 for a brief overview.

System.Security

Types to interface with the underlying structure of the CLR security system, including base classes for permissions. Not covered in this book.

System.Text

Types representing ASCII, Unicode, UTF-8, and other character encodings. Also abstract types for converting blocks of characters to and from blocks of bytes. See Chapters 3 and the section "Using Regular Expressions and Formatting" later in this chapter.

System.Threading

Types for creating and synchronizing threads and, in .NET 4.0, tasks. Also parallel operations and some functionality related to cancellation. See Chapter 13.

System.Web

Types that enable web applications. See Chapter 14.

System.Windows.Forms

Types for creating windowed applications. See Chapter 11.

System.Xml

Types that implement standards-based support for processing XML. See Chapter 9 and 15.

Microsoft.Win32

Types that wrap Win32 API common dialog boxes and components. Not covered in this book.

Namespaces from the F# Libraries

Table 10-3 shows the primary namespaces in F# library DLLs from Table 10-1. The following are opened by default in F# code:

Microsoft.FSharp.Core
Microsoft.FSharp.Collections
Microsoft.FSharp.Control
Microsoft.FSharp.Text

Table 10.3. Namespaces in the DLLs from Table 10-1

Namespace

Description

Microsoft.FSharp.Core

Provides primitive constructs related to the F# language, such as tuples. See Chapter 3.

Microsoft.FSharp.Collections

Provides functional programming collections, such as sets and maps implemented using binary trees. See Chapter 3 and the section "Using Further F# and .NET Data Structures" later in this chapter.

Microsoft.FSharp.Control

Provides functional programming control structures, including asynchronous and lazy programming. Chapter 8 covers programming with the IEvent<'T> type and the IEvent module, and Chapter 13 covers the Async<'T> type.

Microsoft.FSharp.Text

Provides types for structured and printf-style textual formatting of data. See Chapter 4 for an introduction to printf formatting.

Microsoft.FSharp.Reflection

Provides extensions to the System.Reflection functionality that deal particularly with F# record and discriminated unionvalues. See Chapter 9 for a brief introduction, and see the section "Further Libraries for Reflective Techniques" section later in this chapter for more details.

Microsoft.FSharp.Quotations

Provides access to F# expressions as abstract syntax trees. See Chapter 9.

Using the System Types

Table 10-4 shows some of the most useful core types from the System namespace. These types are particularly useful because they take real care to define correctly.

Table 10.4. Useful Core Types from the System Namespace

Function

Description

System.DateTime

A type representing a date and time

System.DayOfWeek

An enumeration type representing a day of the week

System.Decimal

A numeric type suitable for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors

System.Guid

A type representing a 128-bit globally unique ID

System.Nullable<'T>

A type with an underlying value type 'T but that can be assigned null like a reference type

System.TimeSpan

A type representing a time interval

System.Uri

A type representing a uniform resource identifier(URI), such as an Internet URL

The following session shows some sample uses of the DateTime type:

> open System;;
> DateTime.Parse("13 July 1968");;
val it : DateTime = 13/07/1968 00:00:00 {Day = 13;
                                         DayOfWeek = Saturday;
                                         DayOfYear = 195;
                                         Hour = 0;
                                         Millisecond = 0;
                                         Minute = 0;
                                         Month = 7;
                                         Second = 0;
                                         Ticks = 620892000000000000L;
                                         TimeOfDay = 00:00:00;
                                         Year = 1968;}

> let date x = DateTime.Parse(x);;
val date : string -> DateTime

> printfn "date = %A" (date "13 July 1968");;
date = 13/07/1968 00:00:00
val it : unit = ()

> printfn "birth = %A" (date "18 March 2003, 6:21:01pm");;
birth = 18/03/2003 18:21:01
val it : unit = ()

Note that formatting dates depends on the user's localization settings; you can achieve more explicit formatting by using the System.DateTime.ToString overload that accepts explicit format information.

Here you use the System.Uri type to parse a URL:

> open System;;
> System.Uri.TryCreate("http://www.thebritishmuseum.ac.uk/", UriKind.Absolute);;

val it : bool * System.Uri
= (true,
   http://www.thebritishmuseum.ac.uk/
       { AbsolutePath = "/"; ...
         DnsSafeHost = "www.thebritishmuseum.ac.uk"; ...
         Port = 80; ...
         Scheme = "http"; })

> Uri.TryCreate("e3£%//ww.gibberish.com", UriKind.Absolute);;
val it : bool * Uri = (false, null)

Many .NET types are used to hold static functions, such as those for converting data from one format to another. Types such as System.Random play a similar role via objects with a small amount of state. Table 10-5 shows some of the most useful of these types.

Table 10.5. Useful Services from the System Namespace

Function

Description

System.BitConverter

Contains functions to convert numeric representations to and from bit representations

System.Convert

Contains functions to convert between various numeric representations

System.Math

Contains constants and static methods for trigonometric, logarithmic, and other common mathematical functions

System.Random

Provides objects to act as random-number generators

System.StringComparer

Provides objects implementing various types of comparisons on strings (case insensitive, and so on)

Using Regular Expressions and Formatting

In Chapter 3, you saw the different forms of string literals (strings with escape characters, verbatim strings, and byte arrays) and the most typical operations, such as concatenation using string builders. You may also remember that string values are immutable and that string operations that seem to change their input actually return a new string that represents the result. The following sections cover further ways to work with strings and text.

Matching with System.Text.RegularExpressions

One of the most popular ways of working with strings as data is through the use of regular expressions. You do this using the functionality from the .NET System.Text.RegularExpressions namespace. To get started, first note that the F# library includes the following definition:

open System.Text.RegularExpressions
let regex s = new Regex(s)

To this, you can add the following Perl-like operators:

let (=˜) s (re:Regex) = re.IsMatch(s)
let (<>˜) s (re:Regex) = not (s =˜ re)

Here, the inferred types are as follows:

val regex : string -> Regex
val ( =~ ) : string -> Regex -> bool
val ( <>~ ) : string -> Regex -> bool

The infix operators allow you to test for matches:

> let samplestring = "This is a string";;
val samplestring : string

> if samplestring =~ regex "his" then
       printfn "A Match! ";;
A Match!
val it : unit = ()

Regular expressions can include *, +, and ? symbols for zero or more occurrences, one or more occurrences, and zero or one occurrences of the immediately preceding regular expression, respectively, and can include parentheses to group regular expressions. For example:

> "This is a string" =~ regex "(is )+";;
val it : bool = true

Regular expressions can also be used to split strings:

> (regex " ").Split("This is a string");;
val it : string [] = [|"This"; "is"; "a"; "string"|]

Here, you use the regular expression " " for whitespace. In reality, you probably want to use the regular expression " +" to match multiple spaces. Better still, you can match any Unicode whitespace character using s, including end-of-line markers; however, when using escape characters, you should use verbatim strings to specify the regular expression, such as @"s+". Chapter 3 discussed verbatim strings. Let's try this:

> (regex @"s+").Split("I'm a little      teapot");;
val it : string [] = [|"I'm"; "a"; "little"; "teapot"|]

> (regex @"s+").Split("I'm a little  		
	
	 teapot");;
val it : string [] = [|"I'm"; "a"; "little"; "teapot"|]

Here's how to match by using the method Match instead of using =~ and IsMatch. This lets you examine the positions of a match:

> let m = (regex @"joe").Match("maryjoewashere");;
val m : Match

> if m.Success then
     printfn "Matched at position %d" m.Index;;

Matched at position 4
val it : unit = ()

Replacing text is also easy:

> let text = "was a dark and stormy night";;
val text: string

> let t2 = (regex @"w+").Replace(text, "WORD");;
val t2: string  = "WORD WORD WORD WORD WORD WORD"

Here, you use the regular expression "w+" for a sequence of word characters.

Table 10-6 shows the broad range of specifiers you can use with .NET regular expressions.

Table 10.6. Regular Expression Escape Characters

Characters

Description

Ordinary characters

Characters other than . $ ^ { [ ( | ) * + ? match themselves.

.

Matches any character except . If RegexOptions.SingleLine is specified, then it matches every character.

[aeiou0-9]

Matches any of the given characters or character ranges.

[^aeiou0-9]

Matches any character other than the given characters or character ranges.

p{name}

Matches any character in the named character classspecified by {name}. See the .NET documentation for full details.

P{name}

Matches text not included in groups and block ranges specified in {name}.

w

Matches any word character.

W

Matches any nonword character.

s

Matches any whitespace character.

S

Matches any nonwhitespace character.

d

Matches any decimal digit.

D

Matches any nondigit.

a

Matches a bell (alarm) u0007.



Matches a backspace u0008 if in a [] character class; otherwise, in a regular expression,  denotes a word boundary (between w and W characters). In a replacement pattern,  always denotes a backspace.

Matches a tab u0009.

Matches a carriage return u000D.

v

Matches a vertical tab u000B.

f

Matches a form feed u000C.

Matches a new line u000A.

e

Matches an escape u001B.

digit

Matches a back reference.

40

Matches an ASCII character as octal.

x20

Matches an ASCII character using hexadecimal representation (exactly two digits).

cC

Matches an ASCII control character; for example, cC is Ctrl+C.

u0020

Matches a Unicode character using hexadecimal representation (exactly four digits).

When followed by a character that isn't recognizedas an escaped character, matches that character. For example, * is the same as x2A.

You can specify case-insensitive matches by using (?i) at the start of a regular expression:

> samplestring =˜ regex "(?i)HIS";;
val it : bool = true

> samplestring =˜ regex "HIS";;
val it : bool = false

Here is a final example, showing the use of named groups:

let entry = @"
Jolly Jethro
13 Kings Parade
Cambridge, Cambs CB2 1TJ
"

let re =
 regex @"(?<=
)s*(?<city>[^
]+)s*,s*(?<county>w+)s+(?<pcode>.{3}s*.{3}).*$"

You can now use this regular expression to match the text and examine the named elements of the match:

> let r = re.Match(entry);;
val r : Match

> r.Groups.["city"].Value;;
val it : string = "Cambridge"

> r.Groups.["county"].Value;;
val it : string = "Cambs"

> r.Groups.["pcode"].Value;;
val it : string = "CB2 1TJ"

You can also combine regular expression matching with active patterns, described in Chapter 9. For example:

let (|IsMatch|_|) (re: string) (inp:string) =
    if Regex(re).IsMatch(inp)  then Some() else None

let (|MatchGroups|_|) (re: string) (inp:string) =
    let results = Regex(re).Match(inp)
    if results.Success then Some results.Groups else None

These active patterns can now be used as follows:

> match "This is a string" with
| IsMatch "(?i)HIS" -> "yes, it matched"
| IsMatch "ABC" -> "this would not match"
| _ -> "nothing matched"

val it : string = "yes, it matched "

> match "This is a super string" with
  | MatchGroups "(?<word1>Tw+).*(?<word2>sw+)" groups ->
      (groups.["word1"].Value, groups.["word2"].Value)
  | _ -> failwith "nothing matched"

val it : string * string = ("This", "string")

Finally, you can use the dynamic operator, also defined in Chapter 9, to make the lookups slightly more natural:

> match "This is a string is super" with
  | MatchGroups "(?<word1>Tw+).*(?<word2>sw+)" groups -> (groups?word1, groups?word2)
  | _ -> failwith "nothing matched"

val it : string * string = ("This", "super")

Note

.NET regular expressions have many more features than those described here. For example, you can compile regular expressions to make them match very efficiently. You can also use regular expressions to define sophisticated text substitutions.

Formatting Strings Using .NET Formatting

Throughout this book, you've used F# printf format strings to format text and output; Chapter 4 introduced the basic format specifiers for this kind of text formatting. Functions such as printf and printfn are located in the Microsoft.FSharp.Text.Printf module.

Another way to format strings is to use the System.String.Format static method or the other .NET composite formatting functions such as System.Console.WriteLine and TextWriter.WriteLine. This is a distinct set of formatting functions and directives redesigned and implemented from the ground up for the .NET platform. Like printf, these methods take a format specifier and the objects to be formatted. The format specifier is a string with any number of format items acting as placeholders and designating which object is to be formatted and how. Consider the following simple example:

> System.String.Format("{0} {1} {2}", 12, "a", 1.23);;
val it : string = "12 a 1.23"

Each format item is enclosed in braces giving the index of the object to be formatted, and each can include an optional alignment specification (always preceded by a comma after the index, giving the width of the region in which the object is to be inserted, as in {0, 10}) and a format type that guides how the given object is formatted (as in {0:C}, where C formats as a system currency). The general syntax of the format item is as follows:

{index[,alignment][:formatType]}

You can use the alignment value to pad the formatted object with spaces; text alignment is left if its value is negative and right if positive. Table 10-7 summarizes the most often used format types.

Table 10.7. The .NET Format Specifiers

Specifier

Type

C

Currency

D

Decimal/long date

E

Scientific

F

Fixed-point

G

General

N

Number

P

Percent

X

Hexadecimal

d/D

Short/long date

t/T

Short/long time

M

Month

Y

Year

You can find more information about .NET composite formatting at www.expert-fsharp.com/Topics/ TextFormatting.

Encoding and Decoding Unicode Strings

It's often necessary to convert string data between different formats. For example, files read using the ReadLine method on the System.IO.StreamReader type are read with respect to a Unicode encoding. You can specify this when creating the StreamReader; if left unspecified, the .NET librariesattempt to determine the encoding for you.

One common requirement is to convert strings to and from ASCII representations, assuming that all the characters in the strings are in the ASCII range 0 to 127. You can do this using System.Text.Encoding.ASCII.GetString and System.Text.Encoding.ASCII.GetBytes. Table 10-8 shows the predefined encodings and commonly used members in the System.Text.Encoding type.

Table 10.8. Types and Members Related to Unicode Encodings

Type/Member

Description

System.Text.Encoding

Represents a character encoding

UTF8 : Encoding

The encoding for the UTF-8 Unicode format

ASCII : Encoding

The encoding for the ASCII 7-bit character set

Unicode : Encoding

The encoding for the UTF-16 Unicode format

UTF32 : Encoding

The encoding for the UTF-32 Unicode format

GetEncoding : string -> Encoding

Fetches an encoding by name

member GetBytes : string -> byte[]

Encodes a string to bytes

member GetChars: byte[] -> char[]

Decodes a sequence of bytes

member GetString : byte[] -> string

Decodes a sequence of bytes

Encoding and Decoding Binary Data

Another common requirement is to convert binary data to and from the standard 64-character string-encoded representation of binary data used in XML, e-mail, and other formats. You can do this using System.Convert.FromBase64String and System.Convert.ToBase64String.

Using Further F# and .NET Data Structures

As you saw in Chapter 2, F# comes with a useful implementation of some functional programming data structures. Recall that functional data structures are persistent: you can't mutate them, and if you add an element or otherwise modify the collection, you generate a new collection value, perhaps sharing some internal nodes but from the outside appearing to be a new value.

Table 10-9 summarizes the most important persistent functional data structures that are included in FSharp.Core.dll. It's likely that additional functional data structures will be added in future F# releases.

Table 10.9. The F# Functional Data Structures from Microsoft.FSharp.Collections

Type

Description

List<'T>

Immutable lists implemented using linked lists

Set<'T>

Immutable sets implemented using trees

Map<'Key,'Value>

Immutable maps (dictionaries) implemented using trees

LazyList<'T>

Lists generated on demand, with each element computed only once

System.Collections.Generic and Other .NET Collections

Table 10-10 summarizes the imperative collections available in the System.Collections.Generic namespace.

Table 10.10. The .NET and F# Imperative Data Structures from System.Collections.Generic

Type

Description

List<'T>

Mutable, resizable integer-indexed arrays, usuallycalled ResizeArray<'T> in F#.

SortedList<'T>

Mutable, resizable lists implemented using sorted arrays.

Dictionary<'Key,'Value>

Mutable, resizable dictionaries implemented using hash tables.

SortedDictionary<'Key,'Value>

Mutable, resizable dictionaries implemented using sorted arrays.

Queue<'T>

Mutable, first-in, first-out queues of unbounded size.

Stack<'T>

Mutable, first-in, last-out stacks of unbounded size.

HashSet<'T>

Mutable, resizable sets implemented using hash tables. New in .NET 3.5. The F# library also defines a Microsoft.FSharp.Collections.HashSet type usable in conjunction with earlier versions of .NET.

Introducing Microsoft.FSharp.Math

The F# Power Pack is an open source library found on www.codeplex.com. It includes a namespace Microsoft.FSharp.Math that defines a number of mathematical-related constructs, including matrix and vectortypes, double-precision complex numbers (type Complex, abbreviated complex), and arbitrary-precision rationals (type BigNum, abbreviated bignum).

Using Matrices and Vectors

The F# Power Pack includes matrix and column vector types, which are generic and called Matrix<'T> and Vector<'T>, respectively. For symmetry, a type of row vectors, RowVector<'T>, is also included. Most commonly, the element types are instantiated to be double (that is, float), so the following abbreviations are used:

type vector = Vector<float>
type matrix = Matrix<float>
type rowvec = RowVector<float>

The modules Matrix, Vector, and RowVector in the Microsoft.FSharp.Math namespace have many additional functions for creating and working with these types. The functions are specialized for use with floating-point matrices, but versions to work with generic types are available at Microsoft.FSharp.Math.Matrix.Generic and Microsoft.FSharp.Math.Vector.Generic. The functions vector and matrix are also available for creating literal values. Here are some examples that use these types and functions:

> #r "FSharp.PowerPack.dll";;

> open Microsoft.FSharp.Math;;

> vector [ 1.0; 2.0 ; 3.0 ] + vector [ 1.0; 2.0 ; 3.0 ];;
val it : Vector<float> = vector [2.0; 4.0; 6.0]

matrix [ [ 1.0; 2.0 ];
           [ 1.0; 3.0 ] ]
  *
  matrix [ [ 1.0; −2.0 ];
           [ 0.5; 3.0 ] ];;
val it : Math.matrix = matrix [[2.0; 4.0];
                               [2.5; 7.0];]

Table 10-11 summarizes the primary properties of these types.

Table 10.11. The Microsoft.FSharp.Math Matrix and Vector Types

Type/Member

Member Type

Description

type Matrix<'T>

  

.[]

: int * int -> 'T with set, get

Gets or sets the item at the given position in thematrix.

Dimensions

: int * int

Gets the number of (rows, columns) in the matrix.

NumCols

: int

Gets the number of columns in the matrix.

NumRows

: int

Gets the number of rows in the matrix.

GetSlice2D

: ?int * ?int * ?int * ?int -> Matrix<'T>

Gets a submatrix. See the slice syntax for arrays,also usable for matrices, in Chapter 4.

Transpose

: Matrix<'T>

Gets the transpose of the matrix.

type Vector<'T>

  

.[]

: int -> 'T with set, get

Gets or sets the item at the given position in the vector.

NumRows

: int

Gets the number of rows in the vector.

GetSlice

: ?int * ?int -> Vector<'T>

Gets a subvector.

Transpose

: RowVector<'T>

Gets the transpose of the vector.

Using Operator Overloads on Matrices and Vectors

The F# matrix, vector, and row vector types support the use of operators such as +, -, and *. Table 10-12 sxshows some of the overloads supported.

Table 10.12. Primary Operator Overloads Supported by the F# Matrix and Vector Types

Operator

Overload

Description

( * )

: Matrix<'T> * 'T -> Matrix<'T>

Scalar-matrix multiplication, and so on

( * )

: 'T * Matrix<'T> -> Matrix<'T>

Scalar-matrix multiplication, and so on

( * )

: RowVector<'T> * Matrix<'T> -> RowVector<'T>

Vector-matrix multiplication

( * )

: Matrix<'T> * Vector<'T> -> Vector<'T>

Matrix-vector multiplication

( * )

: Matrix<'T> * Matrix<'T> -> Matrix<'T>

Matrix multiplication

( .* )

: Vector<'T> * Vector<'T> -> Vector<'T>

Pointwise multiplication

( .* )

: Matrix<'T> * Matrix<'T> -> Matrix<'T>

Pointwise multiplication

( + )

: Vector<'T> * Vector<'T> -> Vector<'T>

Pointwise addition

( + )

: Matrix<'T> * Matrix<'T> -> Matrix<'T>

Pointwise addition

Supervising and Isolating Execution

The .NET System namespace includes a number of useful types that provide functionality related to the execution of running programs in the .NET Common Language Runtime. Table 10-13 summarizes them.

Table 10.13. Types Related to Runtime Supervision of Applications

Function

Description

System.Runtime

Contains advanced types that support compilation and native interoperability.

System.Environment

Provides information about, and the means to manipulate, the current environment and platform.

System.GC

Controls the system garbage collector. Chapter 17 discusses garbage collection in more detail.

System.WeakReference

Represents a weak reference, which references an object while still allowing that object to be reclaimed by garbage collection.

System.AppDomain

Represents an application domain, which is a software-isolated environment where applications execute. Application domains can hold code generated at runtime and can be unloaded.

Further Libraries for Reflective Techniques

As discussed in Chapter 9, .NET and F# programming frequently uses reflective techniques to analyze the types of objects, create objects at runtime, and use type information to drive generic functions in general ways. For example, in Chapter 9, you saw an example of a technique called schema compilation, which was based on .NET attributes, F# data types, and a compiler to take these and use reflective techniques to generate an efficient text file reader and translator. The combination of reflective techniques and .NET generics allows programs to operate at the boundary between statically typed code and dynamically typed data.

Using General Types

There are a number of facets to reflective programming with .NET. In one simple kind of reflective programming, a range of data structures are accessed in a general way. For example, .NET includes a type System.Array that is a parent type of all array types. The existence of this type allows you to write code that is generic over all array types, even one-dimensional and multidimensional arrays. This is occasionally useful, such as when you're writing a generic array printer.

Table 10-14 summarizes the primary general types defined in the .NET Framework.

Table 10.14. General Types in the .NET Framework

Function

Description

System.Array

General type of all array values.

System.Delegate

General type of all delegates.

System.Enum

General type of all enum values.

System.Exception

General type of all exception values.

System.Collections.IEnumerable

General type of all sequence values. This is the nongeneric version of the F# type seq<'T>, and all sequence and collection values are compatible with this type.

System.IComparable

General type of all comparable types.

System.IDisposable

General type of all explicitly reclaimable resources.

System.IFormattable

General type of all types supporting .NET formatting.

System.Object

General type of all values.

System.Type

Runtime representation of .NET types.

System.ValueType

General type of all value types.

Using Microsoft.FSharp.Reflection

In Chapter 9, the schema compiler used functions from the Microsoft.FSharp.Reflection namespace. This namespace is a relatively thin extension of the System.Reflection namespace. It offers an interesting set of techniques to create and analyze F# values and types in ways that are somewhat simpler than those offered by the System.Reflection namespace. These operations are also designed to be used in precompilation phases to amortize costs associated with reflective programming.

Table 10-15 summarizes the two types in this namespace

Table 10.15. Some Operations in the Microsoft.FSharp.Reflection Namespace

Class and Static Members

Description

Microsoft.FSharp.Reflection.FSharpType

Operations to analyze F# types

Microsoft.FSharp.Reflection.FSharpValue

Operations to analyze F# values

Some Other .NET Types You May Encounter

When .NET was first designed, the .NET type system didn't include generics or a general notion of a function type as used by F#. Instead of functions, .NET uses delegates, which you can think of as named function types (that is, each kind of function type is given a different name).

This means you often encounter delegate types when using .NET libraries from F#. Since .NET 2.0, some of these are even generic, giving an approximation to the simple and unified view of function types used by F#. Every .NET delegate type has a corresponding F#function type. For example, the F# function type for the .NET delegate type System.Windows.Forms.PaintEventHandler is obj -> System.Windows.Forms.PaintEventArgs -> unit. You can figure out this type by looking at the signature for the Invoke method of the given delegate type.

.NET also comes with definitions for some generic delegate types. F# tends to use function types instead of these, so you don't see them often in your coding. However, Table 10-16 shows these delegate types just in case you meet them.

Table 10.16. Delegate Types Encountered Occasionally in F# Coding

Function

F# Function Type

Description

System.Action<'T>

'T -> unit

Used for imperative actions.

System.AsyncCallback

System.IAsyncResult -> unit

Used for callbacks when asynchronous actions complete.

System.Converter<'T,'U>

'T -> 'U

Used to convert between values.

System.Comparison<'T>

'T -> 'T -> int

Used to compare values.

System.EventHandler<'T>

obj -> 'T -> unit

Used as a generic event-handler type.

System.Func<'T,'U>

'T -> 'U

A .NET 3.5 LINQ function delegate. Further arity-overloaded types exist accepting additional arguments: for example, System.Func<'T,'U,'V>, System.Func<'T,'U,'V,'W>.

System.Predicate<'T>

'T -> bool

Used to test a condition.

Some Other .NET Libraries

Any review of the libraries that are usable with F# and .NET is necessarily incomplete; too many high-quality .NET libraries are available, and more are appearing all the time. However, people often ask us which libraries we recommend. Table 10-17 shows some of the frameworks and libraries available at the time of writing that we think may be of interest to you.

Table 10.17. Some Frameworks and Libraries Not Covered in This Chapter

Framework/Library Name

Description

CSLA

A .NET-based framework for defining business objects

Extreme Optimization

A commercial math, vector, statistics, and matrix library for .NET.

GTK#

A set of .NET bindings for the GTK+ GUI toolkit, primarily used on Mono to enable windowed applications on Linux and other platforms.

Irrlicht

An open-source, high-performance, real-time 3D engine.

LINQ

Language Integrated Queries, contained in .NET 3.5. See Chapter 15.

Microsoft Robotics Studio

A .NET environment for creating robotics applications that run across a variety of hardware.

Microsoft XNA

A .NET environment for games for Microsoft gaming platforms such as Xbox 360 and Microsoft Windows.

Windows Presentation Foundation (WPF)

The graphical subsystem of .NET 3.0. See Chapter 11.

Windows Communication Foundation (WCF)

A unified framework for building connected systems. Not covered in this book.

Summary

This chapter gave an overview of the primary libraries available for use with a vanilla installation of F# and .NET. Many, many other libraries are available for .NET, and we couldn't possibly cover them in a single book. Many of the design patterns you've seen here recur in those libraries; after you get to know the libraries discussed here, you'll find that other libraries are easy to use.

The chapters that follow dig into applications of F# and the .NET Framework more deeply, looking at some of the libraries discussed in this chapter in more detail.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset