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.
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 |
---|---|
| Minimal system constructs, including the types in the |
| Additional commonly used constructs in namespaces such as |
| See the corresponding namespace in Table 10-2. |
| See the corresponding namespace in Table 10-2. |
| See the corresponding namespace in Table 10-2. |
| See the corresponding namespace in Table 10-2. |
| See the corresponding namespace in Table 10-2. |
| The foundation types for LINQ and some other useful types. From .NET 3.5 onward. |
Core functionality for Windows Presentation Foundation. | |
| Core functionality for Windows Presentation Foundation. |
| Core functionality for Windows Presentation Foundation. |
| 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.
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.
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 |
---|---|
| 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. |
| Types that can be used to represent the elements and structure of a source code document. Not covered in this book. |
| 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. |
| Types that define generic collections. See Chapter4 and the section "Using Further F# and .NET Data Structures" later in this chapter. |
| Types that are used to implement the runtime and design-time behavior of components and controls. See Chapter 11. |
| Types that provide the programming model for handling configuration data. See Chapter 15. |
| Types that represent the ADO.NET database access architecture. See Chapter 15. |
| Types that allow you to interact with system processes, event logs, and performance counters. See Chapter 18. |
| Types that allow access to GDI+ basic graphics functionality. More advanced functionality is provided in the |
| 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. |
| 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. |
| Types for playing and accessing sounds and other media formats. Not covered in this book. .NET 3.0 and later. |
| Types to programmatically access many of the protocols used on modern networks. See Chapters 2 and 14 for examples and a basic overview. |
| Types that retrieve information about assemblies, modules, members, parameters, and other entities in managed code. See Chapter 9 fwor a brief overview. |
| Types for generating .NET code dynamically at runtime. |
| 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. |
Types to interface with the underlying structure of the CLR security system, including base classes for permissions. Not covered in this book. | |
| 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. |
| Types for creating and synchronizing threads and, in .NET 4.0, tasks. Also parallel operations and some functionality related to cancellation. See Chapter 13. |
| Types that enable web applications. See Chapter 14. |
| Types for creating windowed applications. See Chapter 11. |
| Types that implement standards-based support for processing XML. See Chapter 9 and 15. |
| Types that wrap Win32 API common dialog boxes and components. Not covered in this book. |
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 |
---|---|
| Provides primitive constructs related to the F# language, such as tuples. See Chapter 3. |
| 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. |
Provides functional programming control structures, including asynchronous and lazy programming. Chapter 8 covers programming with the | |
| Provides types for structured and |
| Provides extensions to the |
| Provides access to F# expressions as abstract syntax trees. See Chapter 9. |
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 |
---|---|
| A type representing a date and time |
| An enumeration type representing a day of the week |
| A numeric type suitable for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors |
| A type representing a 128-bit globally unique ID |
| A type with an underlying value type |
| A type representing a time interval |
| 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 |
---|---|
| Contains functions to convert numeric representations to and from bit representations |
| Contains functions to convert between various numeric representations |
| Contains constants and static methods for trigonometric, logarithmic, and other common mathematical functions |
| Provides objects to act as random-number generators |
| Provides objects implementing various types of comparisons on strings (case insensitive, and so on) |
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.
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 = ()
> 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 |
| Matches any character except |
| Matches any of the given characters or character ranges. |
| Matches any character other than the given characters or character ranges. |
| Matches any character in the named character classspecified by |
| Matches text not included in groups and block ranges specified in |
| Matches any word character. |
| Matches any nonword character. |
| Matches any whitespace character. |
| Matches any nonwhitespace character. |
Matches any decimal digit. | |
| Matches any nondigit. |
| Matches a bell (alarm) |
Matches a backspace | |
| Matches a tab |
| Matches a carriage return |
| Matches a vertical tab |
| Matches a form feed |
| Matches a new line |
| Matches an escape |
| Matches a back reference. |