F Sharp

F#は、.NETフレームワーク上で動作するマルチパラダイム言語です。この言語は、静的型付け、関数型、オブジェクト指向、および並列プログラミングをサポートしています。
F#は、Microsoft Researchが開発した言語で、機械学習、数値計算、クラウドコンピューティングなどの分野で広く利用されています。この言語は、高い抽象度とシンプルさにより、プログラマーの生産性を向上させます。
本書は、F#の基礎から応用までを網羅した教科書です。読者は、F#でのプログラミングの基礎を身につけ、効率的なアルゴリズムや高度な並列処理の実装までを学ぶことができます。
本書が、F#を学び始める人、またはF#を応用したい人にとっての貴重なリソースとなることを願っています。
F#は、.NET Framework上で動作する関数型プログラミング言語です。 F#は、.NET用の機能を提供する共通言語ランタイム(CLR)の一部です。 F#は2005年にマイクロソフトが開発し、2007年に最初の公開バージョンが登場しました。 F#は、静的型付け、型推論、高階関数、高度なパターンマッチング、および並列プログラミングを簡潔かつ効果的に行うことができます。
F#は、関数型プログラミング言語として設計されています。そのため、F#アプリケーションは、大部分が関数で構成されています。F#は、.NET Frameworkの一部であり、同じライブラリ、ツール、およびリソースにアクセスすることができます。 F#は、C#やVB.NETと同様に、既存の.NETコンポーネント、ライブラリ、クラス、およびモジュールを使用できます。
F#はまた、並列および非同期プログラミングに最適化されています。これらの機能により、大規模な並列計算を効率的かつ簡潔に記述できます。F#は、.NETのAsynchronous Programming Model(APM)やTask-Parallel Library(TPL)など、.NETの標準並列化ライブラリにもアクセスできます。
F#の特徴は以下の通りです。
マルチプラットフォーム対応:F#は、.NET Frameworkや.NET CoreのようなMicrosoftのプラットフォームだけでなく、MonoやUnityなど、さまざまなプラットフォームで動作します。また、F#はWindows、Linux、Mac OS Xなどのオペレーティングシステムでも利用できます。
あなたの環境に応じて、複数の方法でF#をインストールすることができます。
Visual Studioを使用してF#をインストールする場合、Visual Studio Installerがまずインストールされます。初めてVisual Studioをダウンロードする場合は、インストーラから適切なエディションのVisual Studioをインストールしてください。
既にVisual Studioがインストールされている場合は、F#を追加したいエディションの横にある「変更」を選択してください。ワークロードページで、ASP.NETおよびWeb開発ワークロードを選択します。これには、ASP.NET CoreプロジェクトのF#および.NET Coreサポートが含まれています。「選択したすべてをインストールする」を選択して、右下隅の「変更」を選択します。
Visual Studio InstallerでF#が含まれるVisual Studioを開始するには、「Visual Studioで起動」を選択してください。
Visual Studio CodeでF#をインストールする場合、gitがPATHで利用可能であることを確認してください。コマンドプロンプトでgit --versionを入力し、Enterを押すことで確認できます。.NET SDKおよびVisual Studio Codeをインストールしてください。「拡張機能」アイコンを選択し、「Ionide」で検索してください。「Ionide-fsharp」は、Visual Studio CodeでF#をサポートするために必要な唯一のプラグインです。ただし、FAKEサポートを取得するために「Ionide-FAKE」をインストールしたり、パッケージのサポートを取得するために「Ionide-Paket」をインストールすることもできます。FAKEおよびPaketは、プロジェクトのビルドおよび依存関係の管理に使用される、追加のF#コミュニティツールです。Visual Studio for MacでF#をインストールする場合、どの構成を選択しても、F#はデフォルトでインストールされます。インストールが完了したら、「Visual Studioを起動」を選択してください。
MacOS上のFinderを介してVisual Studioを開くこともできます。
ビルドサーバーにF#をインストールする場合、.NET SDKを介して.NET Coreまたは.NET Frameworkを使用している場合は、ビルドサーバーに.NET SDKをインストールするだけです。必要なすべてが含まれています。.NET Frameworkを使用し、.NET SDKを使用していない場合は、Windows ServerにVisual Studio Build Tools SKUをインストールする必要があります。インストーラで、.NETデスクトップビルドツールを選択し、右側のインストーラメニューでF#コンパイラコンポーネントを選択します。
F#はマルチパラダイムプログラミング言語であり、関数型言語の特徴を持っています。F#では、数値式、論理式、文字列式、リスト式、配列式、タプル式など、さまざまな式がサポートされています。
数値式では、算術演算子(+、-、*、/など)や比較演算子(=、<、>など)を使用して、数値計算を行うことができます。例えば、以下のようなコードを書くことができます。
論理式では、論理演算子(&&、||、notなど)を使用して、論理演算を行うことができます。例えば、以下のようなコードを書くことができます。
文字列式では、文字列結合演算子(+)を使用して、文字列を結合することができます。例えば、以下のようなコードを書くことができます。
リスト式では、リスト演算子(::)を使用して、リストを作成することができます。例えば、以下のようなコードを書くことができます。
配列式でもリスト演算子を使用することができますが、それ以外にも様々な関数を使用することができます。例えば、以下のようなコードを書くことができます。
タプル式では、カンマ(,)を使用して、複数の値を1つのオブジェクトにまとめることができます。例えば、以下のようなコードを書くことができます。
以下は F# の制御構造の概要です。
F# では、if/then/else 構文を使って条件分岐を行うことができます。構文は以下の通りです。
例えば、x が 0 より大きい場合には "Positive"、0 の場合には "Zero"、0 より小さい場合には "Negative" という文字列を返す関数を定義すると以下のようになります。
F# では、for ループや while ループを使って反復処理を行うことができます。
例えば、1 から 10 までの合計を計算すると以下のようになります。
上記の for の例と等価なループをwhileで書いた例
F# では、try/with 構文を使って例外処理を行うことができます。
例えば、割り算を行う関数を定義すると以下のようになります。
第 1 引数を第 2 引数で割り、整数の結果を返します。ただし、第 2 引数が 0 の場合は例外が発生し、0 を返します。
F#における関数定義の一般的な書式は以下の通りです。
これらの例を使って、次に示すように関数を呼び出すことができます。
F#で再帰関数を定義する場合は、以下の書式のように rec キーワードを伴って定義します。
たとえば、0からnまでの自然数の和を計算する以下の再帰関数を定義する場合は、以下のように書けます。
この関数を使って、例えばsum 5を評価すると、1 + 2 + 3 + 4 + 5 = 15が返されます。
F#のモジュールは、F#コードの再利用可能な単位であり、関数、型、変数、およびその他の要素を含むことができます。モジュールは、F#コードの構造化された組織化を可能にし、コードの読みやすさ、保守性、および再利用性を向上させます。モジュールは、コードの一部を隠すことができ、カプセル化を実現することができます。F#のモジュールは、別のF#プログラムや.NETアプリケーションで使用することができます。
上記の例では、MyModuleという名前のモジュールを宣言しています。このモジュール内には、addとsubtractという関数が定義されています。add関数は2つの引数を受け取り、それらを加算した結果を返します。subtract関数は同様に2つの引数を受け取り、それらを減算した結果を返します。
このようにモジュールを利用する場合は、以下のように他のファイルでインポートして使用することができます。
ここでは、MyModuleモジュールをopenして他のファイルからアクセスすることができるようになっています。そして、addとsubtractという関数を呼び出しています。これらの関数は、それぞれ引数を与えることで、加算および減算の結果を取得することができます。
F#には、以下のようなデータ型があります。
以上が F# で提供されるデータ型の種類になります。

F#のタプルには以下のような特徴があります。
また、F#のタプルは以下のような使い方ができます。
タプルの値を変数に代入することができます。
タプルを関数の戻り値として使用することができます。
タプルをリストの要素として使用することができます。
以上がF#のタプルに関する機能の一部です。
F#のOption型は、値が存在する場合と存在しない場合の2つの状態を表すために使用されます。Option型はF#標準ライブラリの一部であり、以下のように定義されます。
'Tには任意の型を指定することができます。例えば、Option<int>は整数型の値が存在する場合と存在しない場合の2つの状態を表現するために使用することができます。
Option型には、値が存在するかどうかを確認するために使用できる関数が用意されています。以下にその例を示します。
範囲を持つ値を返す場合、Option型を使用することが一般的です。以下の例は、文字列が数値である場合にその数値を返し、それ以外の場合はNoneを返します。
これを使って、"10"の値を解析すると、結果はSome 10になります。"abc"のように解析できない値の場合は、Noneが返されます。
Option型を使用すると、Nullポインタ例外などのバグを防ぐことができます。しかし、プログラマーが手動でOption型を扱うためのコードを書く必要があるため、多少面倒な面があります。
以下は、Option型の主な操作です。
F#におけるレコードは、フィールドの集合に名前を付けて構造を定義するための機能です。F#のレコードは、.NETのクラスとは異なり、値型(value type)として定義されます。
以下は、F#でレコードを定義する方法と、レコードを使用する方法についての例です。
この例では、Personというデータ型(レコード)を定義し、NameとAgeという2つのフィールドを持たせています。そして、3人の人物情報を含むpersonsという配列を作成し、forループを使用してpersons内の全ての人に関する情報を表示しています。
F#には、共用体(Union Types)と呼ばれる特別なデータ型があります。共用体は、異なる型の値を含むことができるデータ型で、C#のenum型やJavaの列挙型に相当します。F#の共用体は、極めて柔軟で、使いやすいものです。
共用体を定義するには、typeキーワードによる新しい型の定義を行い、|を使って共用体の要素を列挙していきます。共用体の要素は、すべて同じ名前空間に属するものでなければなりません。
以下は、共用体を使用した簡単な例です。
この例では、Shapeという共用体型を定義して、CircleとRectangleという2種類の要素を持たせています。Circle要素は、1つの浮動小数点数を保持し、Rectangle要素は、2つの浮動小数点数を保持します。次に、areaOfShape関数を定義して、引数shapeがCircle要素であれば円の面積、Rectangle要素であれば長方形の面積を計算しています。
共用体を使用すると、複数の関連する値を1つの型にまとめることができ、プログラムの見通しがよくなります。また、異なる型の値を比較する場合にも非常に便利です。しかし、共用体が極めて柔軟であるため、使いすぎるとコードがややこしくなる場合もあります。

以下はF#のコレクションと主なメソッドを表形式でまとめたものです。
上記の表では、各行がメソッド、各列がコレクションを表しています。たとえば、Listという列にあるlength/countというセルは、リストの要素数を取得するためのメソッドであるList.lengthに対応しています。同様に、Seqという列にあるmapというセルは、シーケンスの要素に関数を適用し、新しいシーケンスを作成するためのSeq.mapメソッドに対応しています。
F#において、リストは非常に重要なデータ構造です。F#のリストは不変な一連の値のシーケンスであり、アイテムを追加、削除、変更できません。 ただし、新しいリストを作成することで、既存のリストから要素を削除したり、要素を追加したりすることができます。
F#のリストは、パターンマッチングによって処理されることがよくあります。たとえば、次のようにして、リストの先頭要素と残りのリストを取得することができます。
また、F#のリストは遅延評価されるため、必要に応じて要素を生成するために使用することができます。たとえば、次の関数は、与えられた整数に対する素数を持つ無限リストを生成します。
F#のリストは、高階関数と一緒に使用することができる場合があります。特に、List.map、List.filter、List.foldなどの関数は、リストの要素に対して変換、フィルタリング、畳み込み操作を実行するために使用することができます。
これらの例は、F#のリストに関する機能の一部ですが、F#のリストは非常に強力で、多くの多彩な操作を実行することができます。=== 配列 ===
F#でのシーケンスには、非常に多くの機能があります。以下にいくつかの例を挙げてみます。
これにより、mySeqは1から3までの整数を含むシーケンスとして定義されます。
この場合、evenを出力するまで、numsの要素は実際には計算されません。必要な場合にのみ計算されます。
以上が、F#のシーケンスに関する簡単な説明です。より詳細な情報については、F#の公式ドキュメントを参照してください。
F#には、様々な配列を処理するための便利な組み込み関数が用意されています。以下に、配列に関するいくつかの機能を紹介します。
以上、F#の配列に関するいくつかの機能を紹介しました。F#の配列について詳しく学ぶには、F#の公式ドキュメントを参照してください。
F# の Set は、重複のない要素のコレクションを扱うためのデータ構造です。以下にいくつかの機能を紹介します。
以下は、F# の Set を使用した例です。
F#のMapは、連想配列を表現するためのデータ構造です。以下に、その機能をいくつか紹介します。
Mapの作成、Map.addメソッドの使用、Map.tryFindメソッドの使用、およびMap.foldメソッドの使用を行っています。
F#は、ML系の強力な関数型プログラミング言語です。F#は、高オーダー関数、カリー化、ピュア関数、代数的データ型などの強力な機能を備えています。
まず、高オーダー関数は、関数を引数として受け取る関数または関数を戻り値として返す関数です。これにより、非常に柔軟な関数を作成できます。例えば、以下の高オーダー関数 map は、リストを受け取り、リストの各要素に関数を適用して新しいリストを生成します。
次に、カリー化は、複数の引数をとる関数を、1つの引数をとる関数のチェーンに変換する方法です。カリー化を使用すると、再利用性が高く、より柔軟な関数を作成できます。
さらに、F#はピュア関数の作成を簡単にします。ピュア関数は、副作用がない関数であり、同じ入力に対して常に同じ出力を生成します。F#は、イミュータブル(変更不能)なデータ構造を使用することを推奨しており、これは、新しいデータ構造の生成のみをサポートしています。これにより、予期しない副作用が発生する可能性がある場合にも、安全性を確保することができます。
最後に、F#では、代数的データ型を使用して、異なる種類のデータを表現することができます。代数的データ型には、ユニオン型とレコード型があります。ユニオン型は、複数の型の一つでできる型であり、レコード型は、複数の型のフィールドを持つ型です。
以上がF#の関数型プログラミングの高度な機能です。これらの機能を駆使することで、より柔軟で再利用性の高いプログラムを作成できます。
F#は、.NETフレームワークの一部であり、静的型付きのマルチパラダイムプログラミング言語です。F#の静的型付きシステムは、コンパイラによる静的解析により、実行時のエラーを減らし、保守性を向上させることができます。
F#には静的型付きの変数があり、型に基づいて制限されます。これにより、コードの品質が高く、デバッグが容易になります。また、F#では性能最適化のために、不変性が重視されています。このような不変性は、オブジェクトの状態を常に確実に把握することができるため、コードの可読性も向上します。
F#の静的型付きシステムは、.NETの型システムと高度に統合されています。これは、既存の.NETアプリケーションからの移行が容易であることを意味しています。また、F#は.NETの機能をサポートしており、C#やVB.NETと同じく、完全な相互運用性を持っています。
F#は、静的型付きシステムを活用することで、多くの問題を事前に検出することができます。これにより、バグを未然に防ぐことができるため、ソフトウェア開発の過程での品質と信頼性が向上し、保守性が高まります。
以下は、F#のアクティブパターンマッチングに関する簡単な例です。
この例では、F#でアクティブパターンマッチングがどのように機能するかを示しています。最初に、|Even|Odd|というアクティブパターンを定義します。このパターンは、整数が偶数か奇数かに応じて、2つのパターンマッチングを提供します。次に、isEven関数を定義し、整数をEvenまたはOddにパターンマッチングして、偶数であるかどうかを確認します。
次に、通貨シンボルをパターンマッチングするアクティブパターンを定義します。このアクティブパターンは、DollarとEuroという2つのパターンを提供し、文字列がドルまたはユーロの通貨記号であるかを確認します。convertPrice関数は、通貨シンボルと価格を受け取り、Dollarの場合は価格をユーロに変換し、Euroの場合は変換を行わずに価格を返します。最後に、printfnを使用して、アクティブパターンを使用した変換の例を示します。
私たちが使用したprintfn関数は、文字を出力するための簡単な関数で、%dや%sといったフォーマット指示子を使用して、変数の値を表示することができます。
F#は、.NET Frameworkの一部であるため、マルチスレッドや並列処理をサポートしています。F#の並列処理は、以下の2種類の方法で実現できます。
Asyncパターンは、.NET Framework 4.0以降で導入された非同期処理のためのパターンです。Asyncパターンを使用することで、マルチスレッドを使用した並列処理よりもコードがシンプルになります。以下は、Asyncパターンを使用したF#のコードサンプルです。
このコードでは、Asyncパターンを使用して、2つのWebページを並列でダウンロードし、それぞれのサイズを表示しています。
Parallelパターンは、TPL(Task Parallel Library)の一部であるため、.NET Framework 4.0以降で利用できます。Parallelパターンを使用することで、C#のTaskやThreadPool、PLINQなどと同様に、簡単に並列処理を実現することができます。以下は、Parallelパターンを使用したF#のコードサンプルです。
このコードでは、Parallelパターンを使用して、1~1,000,000の範囲内の素数を探索しています。既存のfindPrimesInRange関数を使用し、それを各々のチャンク(プロセッサ数に合わせて分割された入力リストのサブリスト)に対してマップしています。マップされた結果を一つのリストに連結することで、最終的な素数リストを作成します。また、sw.TimeItを使用することで、実行時間を計測しています。
これら2つのパターンは、さまざまなシナリオに応じて適用することができます。Asyncパターンは、I/OバウンドのアプリケーションやWebサービスなどの非同期処理に適しています。また、Parallelパターンは、CPUバウンドの重い演算などに適しています。F#の並列処理は、.NET Frameworkの豊富な並列処理ライブラリを活用しつつ、F#の関数型プログラミングの利点を生かした柔軟な並列処理を実現することができます。
F#の非同期処理に関するサンプルコードです。
このコードでは、downloadAsync関数は、 asyncキーワードで修飾された非同期関数として定義されています。この関数は、System.Net名前空間内にあるWebClientクラスを使用して、指定されたUriからHTMLをダウンロードします。
let! html = webClient.AsyncDownloadString(url)のように、let!を使用して非同期操作の結果を待つことができます。let!は通常のletキーワードと似ていますが、非同期操作が完了するまで、他の処理をブロックせずに待機します。
Async.RunSynchronously関数を使用することで、非同期操作を同期的に実行できます。この場合、downloadTask変数に格納された非同期タスクを実行して、ダウンロード処理が完了するまでブロックします。
最後に、printfn関数を使用して、ダウンロードが完了したことをユーザーに通知します。
Ruby#コードギャラリーからの移植です。
エラトステネスの篩を、若干 F# らしく書いてみました。
最大公約数と最小公倍数を、若干 F# らしく書いてみました。
二分法を、若干 F# らしく書いてみました。