情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

F#入門(13)ユニオン型

ユニオン型(union type)とは、それぞれ別のデータ構造(または意味)を持った複数のコンストラクタを持ち、その内のどれを使ってでもその型のオブジェクトを実体化できるような型のことです。

普通の型の値はコンパイル時にあるデータ構造に決定されてしまいますが、ユニオン型の値は実行時に(コンパイル時に定められた)複数のデータ構造から選択することが可能です。

ある値が幾つかのデータ構造の候補の中からどれか一つを選択できるようにしたい場合に便利です。

最初の例ではOnコンストラクタとOffコンストラクタを持ったbutton型を定義しています。

ユニオン型を定義する場合も、他の型と同じようにtypeキーワード、型名、等号の順に並べます。以降、幾つかのコンストラクタが続きます。コンストラクタは縦線で区切ります。

コンストラクタは、大文字から始まるコンストラクタ名から構成されます。コンストラクタ名は、一つの型の中では一意でなければなりませんが、別々の型で同じコンストラクタ名を使用することは可能です(その場合、型注釈が必要となる可能性があります)。

type button =

    | On

    | Off

ここで定義されたOnコンストラクタ及びOffコンストラクタはbutton型の値として使用可能です。両コンストラクタともbutton型と推論されることに注意してください。

let on = On

let off = Off

パターンマッチングについてはまだ包括的な説明をしていませんが、以下のようにすることで与えられた値の持つコンストラクタによって場合分けができます。

let print_button x =

    match x with

    | On  -> printfn "On"

    | Off -> printfn "Off"

print_button On

print_button Off

先程の例では、コンストラクタに何も情報が付加されていませんでした。これではあまり使い途がありません。

しかしながら、コンストラクタは引数を取ることができ、何らかのデータを付加させることができます。

引数はコンストラクタ名の後にofキーワードと型名を書くことで指定することができます。複数の引数を取らせたい場合はタプルを使います。その場合、型指定の方法はタプルと同じです。

先述の例のOnコンストラクタにint型とstring型の2個の引数を付加した例は次のようになります。

type button =

    | On  of int * string

    | Off

このOnコンストラクタを使う場合は次のようにコンストラクタ名の後に引数を指定します。この場合は、引数が2つなのでタプルと同じように全体を括弧で囲み要素をカンマで区切ります。

let on = On(1, "F#")

ユニオン型の値から引数を取り出したい場合はパターンマッチングを使います。その場合はコンストラクタ名の後に引数を代入するための識別子を指定します。

let print_button x =

    match x with

    | On (a, b) -> printfn "%i, %s" a b

    | Off       -> printfn "Off"

print_button (On(1, "F#"))

ユニオン型の使用例として、摂氏温度、華氏温度、ケルビンを選択的に表現できるtemprature型を以下に挙げます。

type temperature =

    | Celsius of float

    | Fahrenheit of float

    | Kelvin of float

この型の値は下のように作成できます。

let t1 = Celsius 150.0

let t2 = Fahrenheit 98.6

let t3 = Kelvin 5.0

摂氏温度、華氏温度、ケルビンを相互変換する関数はパターンマッチングを使って以下のように定義できます。

let convert_to_celsius x =

    match x with

    | Celsius    x -> x

    | Fahrenheit x -> (x ? 32.0) * (5.0/9.0)

    | Kelvin     x -> x ? 273.15

let convertToFahrenheit x =

    match x with

    | Celsius    x -> x * (9.0/5.0) + 32.0

    | Fahrenheit x -> x

    | Kelvin     x -> x * (9.0/5.0) ? 459.67

let convertToKelvin x =

    match x with

    | Celsius    x -> x + 273.15

    | Fahrenheit x -> (x + 459.67) * (5.0/9.0)

    | Kelvin     x -> x

ユニオン型のデータ構造は再帰的に定義することもできます。

別の使用例として、ユニオン型を使った二分木の表現を以下に示します。

type binary_tree =

    | Leaf

    | Node of binary_tree * binary_tree

この型の値は下のように作成できます。

let bt = Node(Node(Leaf, Node(Leaf, Leaf)), Leaf)
pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-F#