option型
F#で使える便利な型の一つにoption型があります。
これを使うと、「値がないか、何かの値がある」ことを表すことが出来ます。
option型の簡略化した定義は次のようになります(Expert F# p37より)
(正確な定義はf#4.1 spec 18.4.2 The Option typeを参考。このページの下部にも載せています。)
これは判別共用体と呼ばれるものになります。
- option型の簡略版定義
-
type 'a option =
| None //値がない場合
| Some of 'a //値がある場合
例えばoption型の値は次のようになります。
Noneのほうは多相的な型になっている点に注意
option型の値
> Some 3;;
val it : int option = Some 3
> Some "hello";;
val it : string option = Some "hello"
> None;;
val it : 'a option = None
option型は、「失敗する可能性のある計算」、
例えば要素の探索で利用出来ます。
実際、F#のListモジュールには、option型を使って
探索結果を返すtryfindという関数があります。
tryfindの例
> List.tryFind ((=)1) [2;3;4];;
val it : int option = None
> List.tryFind ((=)2) [2;3;4];;
val it : int option = Some 2
このコードは[2;3;4]というリストに
1または2があるかを調べています。
上の例では、一致するデータがないため
None型のデータが返っています。
また、Noneの型は'a optionでなくint optionになっている点にも注目
※なお、Listモジュールには
List.findというoption型を使わず例外を出すバージョンもあります
ここで、(=)のようにイコールをかっこで囲むと2引数関数のように扱えます
さらに、((=)1)のように引数を一つ与えるとカリー化されて
1と等しいか比べる1引数関数のようになります。
カリー化についてはカリー化のページで解説します。
option型のデータを操作するには
パターンマッチを用います。
例えばint option型の値を受け取り、
値があれば1を足したint option型の型を返す関数は
次のように記述出来ます。
option型の操作
let add1 a =
match a with
| None -> None
| Some(x) -> Some(x+1);;
let print_any = printfn "%A";;
print_any (add1 (Some 2));;
print_any (add1 None);;
//Some 2 |> add1 |> print_any;;
//None |> add1 |> print_any;;
ただし、option型の基本的な操作に関しては
Optionモジュールで定義されており
上のadd1は次のように定義することが出来ます。
Optionモジュールの利用
let add1 a = Option.map ((+)1) a;;
Option.mapもList.mapやArray.mapと基本的に使い方は同じで
Some(a)をSome(f a)という値に変更して返します。
また、Noneが入力された場合はNoneを返します
他に基本的な関数としては
Some型であるかを判定するisSome
None型であるかを判定するisNone
Some型であればその値を返すget
などがあります。
Optionモジュールの利用2
let s = Some 1;;
let n = None;;
s.IsSome;; //true.下のoption型の定義参考
Option.isSome s;; //true
Option.isSome n;; //false
Option.isNone s;; //false
Option.isNone n;; //true
Option.get s;; //1
//Option.get n;; //Error. System.ArgumentException
Optionモジュールのその他の部分については
Option Moduleを参照ください
最後にoption型の正確な定義を載せます(F# 4.1 spec 18.4.2)
- option型の正確な定義
-
[<DefaultAugmentation(false)>]
[<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>]
type 'T option =
| None
| Some of 'T
static member None : 'T option
static member Some : 'T -> 'T option
[<CompilationRepresentation(CompilationRepresentationFlags.Instance)>]
member Value : 'T
member IsSome : bool
member IsNone : bool