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
.