CodeZine(コードジン)

特集ページ一覧

F#の言語指向プログラミング(LOP)概論と抽象的表現

C#プログラマのためのF#入門(7)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2010/06/24 14:00

目次

3種類のLOP

 F#のLOPは大きく分けて以下の3種類に分類できます。

  1. Abstract Representation(抽象的表現)

     ホスト言語F#を利用して、あるドメインに対して、より見やすく利用価値の高いAPI、つまり内部DSLを作成します。

  2. Concrete Representation(具体的表現)

     他の言語で表されたドメインの問題をF#にロードします。XML設定ファイル、CSVなどを編集ファイルとしてDSLを作成します(外部DSLの使用)。

  3. Computation representation(計算機的表現)

     F#で書かれたコード内の演算表現を独得の機能を果たすように操作するか、もしくは他の言語に変換します。例えば、ワークフローや、クエリーの操作が当てはまります。

 今回は上記の3種類のうち、F#によるAbstract Representation(抽象的表現)について紹介します。

Abstract Representation(抽象的表現)

 コンパイラ内部ではソースコードはシンタックスツリー(構文木)として表現されます。F#ではそのシンタックスツリーを型に変換できます。それらの型や、効率よいパターンマッチを利用して内部DSLを作成できます。F#のサブセットとしてのDSLが、問題の本質を比較的自然な形で表現できるのが、F#の抽象的表現の特徴です。

オプション型

 抽象的表現の代表的な機能としてまず、オプション型というタイプがあります。C#にはNullable型というタイプがあります。これは、通常Null値を取ることができない値型の変数にNull値を持たすことを可能とし、値があるかないか、ある場合にはその値は何か、という情報を持つことができる型です。F#のオプション型はこのNullable型にとてもよく似ています。しかし、Nullable型は、値型にのみ有効ですが、オプション型は全てのジェネリックな型に対して有効であるという点が異なります。

[リスト1]C#のNullable型の例
//int型の変数にはそのままではnullはバインドできない。
//int x = null; ※1
//intは値型なのでNullable型に変更できる
int? y = null;  //※2
int? z = 1;  //※3
//stringは参照型なのでNullable型にできない
//string? w = "aaa";※4

 ※1のようにint型の変数にはnullは割り当てられません。しかし、int型はNullable型に変換できるため、※2※3のようにして、nullもしくはint型の値を設定することは可能です。参照型の変数をNullable型にすることはできないため、※4のようにstringをNullable型に変換することはできません。

 次にF#のオプション型を見てみましょう。

 オプション型の構文は以下のようになります。

[構文]オプション型
----------------------------------------
type ジェネリックな型 変数名 =
| None
| Some of 'ジェネリックな型
----------------------------------------

 では、上記の構文を用いて、先ほどC#のNullable型で定義したものをF#のオプション型を使用して表現してみましょう。

[リスト2]F#のオプション型の定義の例
type 'a option =
| None
| Some of 'a;;
//xにオプショナル型値なし(None)を束縛。
let x = None;; //※5
//yに値あり値は1(int)を束縛
let y = Some 1;; //※6
//yに値あり値は”aaa”(string)を束縛
let z = Some "aaa";; //※7

 ▼

type 'a option =
  | None
  | Some of 'a
>
val x : 'a option
>
val y : int option = Some 1
> 
val z : string option = Some "aaa"

 上記の例の場合、Someの値はint型(※6)にもstring型(※7)にもなる可能性があります。連載第3回目にて、関数などのパラメータ化によりジェネリック(一般化)にできると解説しましたが、オプション型の型定義もパラメータにしてジェネリックにすることが可能です。Noneはnullのようなものです(※5)。実際にはこのoption型は、コンパイラ起動時からデフォルトで定義されています。

 このオプション型の利用例として、リストの探索結果を返すtryFindと言う関数を紹介します。以下の例は、リストにある数値があるかどうかを判定させる関数です。

[リスト3]tryFind関数
//リスト内に100という値があるかどうかの結果を返したい場合。
List.find (fun x -> x = 100) [1..10];;
//tryFind関数はオプション型を返すので値がない場合にはNoneを返す。※2
List.tryFind (fun x -> x = 100) [1..10];;
//tryFind関数はオプション型を返すので値がある場合には値があるということと、その値を返す。※3
List.tryFind (fun x -> x = 10) [1..10];;

 ▼

System.Collections.Generic.KeyNotFoundException: Exception of type 'System.Collections.Generic.KeyNotFoundException' was thrown.
   at Microsoft.FSharp.Collections.ListModule.Find[T](FSharpFunc`2 predicate, FSharpList`1 list)
   at <StartupCode$FSI_0006>.$FSI_0006.main@()
Stopped due to error
>
val it : int option = None
>
val it : int option = Some 10

 List.find関数はリスト内に100という値がない場合、エラーを返します(※1)。しかし、tryFind関数はオプション型を返すので値がない場合にはエラーの代わりにNoneを返します(※2)。ある場合には、Some値を表示します(※3)。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:C#プログラマのためのF#入門

もっと読む

著者プロフィール

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

  • WINGSプロジェクト 星山 仁美(ホシヤマ ヒトミ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5