Muokkaa

Jaa


Options

The option type in F# is used when an actual value might not exist for a named value or variable. An option has an underlying type and can hold a value of that type, or it might not have a value.

Remarks

The following code illustrates a function which generates an option type.

let keepIfPositive (a: int) = if a > 0 then Some(a) else None

As you can see, if the input a is greater than 0, Some(a) is generated. Otherwise, None is generated.

The value None is used when an option does not have an actual value. Otherwise, the expression Some( ... ) gives the option a value. The values Some and None are useful in pattern matching, as in the following function exists, which returns true if the option has a value and false if it does not.

let exists (x: int option) =
    match x with
    | Some(x) -> true
    | None -> false

Using Options

Options are commonly used when a search does not return a matching result, as shown in the following code.

let rec tryFindMatch pred list =
    match list with
    | head :: tail -> if pred (head) then Some(head) else tryFindMatch pred tail
    | [] -> None

// result1 is Some 100 and its type is int option.
let result1 = tryFindMatch (fun elem -> elem = 100) [ 200; 100; 50; 25 ]

// result2 is None and its type is int option.
let result2 = tryFindMatch (fun elem -> elem = 26) [ 200; 100; 50; 25 ]

In the previous code, a list is searched recursively. The function tryFindMatch takes a predicate function pred that returns a Boolean value, and a list to search. If an element that satisfies the predicate is found, the recursion ends and the function returns the value as an option in the expression Some(head). The recursion ends when the empty list is matched. At that point the value head has not been found, and None is returned.

Many F# library functions that search a collection for a value that may or may not exist return the option type. By convention, these functions begin with the try prefix, for example, Seq.tryFindIndex.

Options can also be useful when a value might not exist, for example if it is possible that an exception will be thrown when you try to construct a value. The following code example illustrates this.

open System.IO

let openFile filename =
    try
        let file = File.Open(filename, FileMode.Create)
        Some(file)
    with ex ->
        eprintf "An exception occurred with message %s" ex.Message
        None

The openFile function in the previous example has type string -> File option because it returns a File object if the file opens successfully and None if an exception occurs. Depending on the situation, it may not be an appropriate design choice to catch an exception rather than allowing it to propagate.

Additionally, it is still possible to pass null or a value that is null to the Some case of an option. This is generally to be avoided, and typically is in routine F# programming, but is possible due to the nature of reference types in .NET.

Option Properties and Methods

The option type supports the following properties and methods.

Property or method Type Description
None 'T option A static member that creates an option value that has the None value.
IsNone bool Returns true if the option has the None value.
IsSome bool Returns true if the option has a value that is not None.
Some 'T option A static member that creates an option that has a value that is not None.
Value 'T Returns the underlying value, or throws a System.NullReferenceException if the value is None.

Option Module

There is a module, Option, that contains useful functions that perform operations on options. Some functions repeat the functionality of the properties but are useful in contexts where a function is needed. Option.isSome and Option.isNone are both module functions that test whether an option holds a value. Option.get obtains the value, if there is one. If there is no value, it throws System.ArgumentException.

The Option.bind function executes a function on the value, if there is a value. The function must take exactly one argument, and its parameter type must be the option type. The return value of the function is another option type.

The option module also includes functions that correspond to the functions that are available for lists, arrays, sequences, and other collection types. These functions include Option.map, Option.iter, Option.forall, Option.exists, Option.foldBack, Option.fold, and Option.count. These functions enable options to be used like a collection of zero or one elements. For more information and examples, see the discussion of collection functions in Lists.

Converting to Other Types

Options can be converted to lists or arrays. When an option is converted into either of these data structures, the resulting data structure has zero or one element. To convert an option to an array, use Option.toArray. To convert an option to a list, use Option.toList.

See also