チュートリアル: Visual F# を使用したアプリケーションの作成、デバッグ、および配置
このチュートリアルでは、Visual Studio 2010 で .NET Framework 4 と共に F# を使用する手順を紹介します。
このチュートリアルでは、米国財務省の金利情報について、これまでのデータを分析する例を取り上げ、Visual Studio 2010 を使用して F# アプリケーションを記述する方法を説明します。 まず F# の対話形式のウィンドウを使用して簡単な分析を行い、次にデータを分析するコードを記述してテストします。その後、C# のフロントエンドを追加して、作成した F# コードを他の .NET 言語と統合する方法を示します。
必須コンポーネント
このチュートリアルを実行するには、次のコンポーネントが必要です。
- Visual Studio 2010
注意
お使いのマシンで、Visual Studio ユーザー インターフェイスの一部の要素の名前や場所が、次の手順とは異なる場合があります。 これらの要素は、使用している Visual Studio のエディションや独自の設定によって決まります。 詳細については、「Visual Studio の設定」を参照してください。
F# スクリプトを作成するには
まず、F# スクリプトを作成します。 [ファイル] メニューの [新規作成] をポイントし、[ファイル] をクリックします。 [新しいファイル] ダイアログ ボックスで、[インストールされたテンプレート] の [スクリプト] を選択し、[F# スクリプト ファイル] を選択します。 [開く] をクリックしてファイルを作成し、RateAnalysis.fsx という名前で保存します。
.NET と F# API を使用して、米国連邦準備銀行のインターネット サイトのデータにアクセスします。 次のコードを入力します。
open System.Net open System.IO let url = sprintf "http://www.federalreserve.gov/releases/h15/data/business_day/H15_TCMNOM_Y10.txt" let req = WebRequest.Create(url, Timeout = 10000000) let resp = req.GetResponse() let stream = resp.GetResponseStream() let reader = new StreamReader(stream) let csv = reader.ReadToEnd()
次の点に注意してください。
文字列とキーワードは色分けして表示されます。
ピリオド (.) を入力すると、入力候補一覧が表示されます。
メソッド名やその他の識別子を Visual Studio によって完成させることができます。これを行うには、識別子の途中でショートカット キー Ctrl + Space または Ctrl +J を使用します。 Ctrl + J キーを使用した場合は、入力候補一覧が表示されます。
コードで識別子の上にマウス ポインターを置くと、その識別子についての情報を示すツールヒントが表示されます。
WebRequest にカーソルがあるときに F1 キーを押すと、関連するドキュメントが表示されます。
let にカーソルがあるときに F1 キーを押すと、関連するドキュメントが表示されます。
mscorlib.dll、System.dll、および System.Windows.Forms.dll の型と名前空間が既定で参照されます。
ここで設定される Timeout 値は、コンストラクター引数ではなく、プロパティです。 F# では、この方法でプロパティ値を設定できます。
この例の URL をブラウザーにコピーすると、米国連邦準備銀行によって公開されている、日付と金利を含むコンマ区切りの値の一覧が返されます。
ここで、F# Interactive を使用してコードを実行できます。 すべてのコードを選択し (マウスを使用するか、Ctrl キーを押しながら A キーを押します)、右クリックして、[Interactive に送信] をクリックします (または、Alt + Enter キーを押します)。
[F# Interactive] ウィンドウがまだ表示されていない場合は、表示されます。
コードが正常に実行されます。
[F# Interactive] ウィンドウに次の結果が表示されます。
val url : string = "http://www.federalreserve.gov/releases/h15/data/business_day/"+[18 chars] val req : System.Net.WebRequest val resp : System.Net.WebResponse val stream : System.IO.Stream val reader : System.IO.StreamReader val csv : string = " ,Instrument,"U.S. government securities/Treasury constant m"+[224452 chars] >
次に、F# Interactive を使用してデータを調べます。 F# Interactive プロンプトで、「csv;;」と入力し、Enter キーを押します。 「csv.Length;;」と入力し、Enter キーを押します。 次の点に注意してください。
データは最新です。
F# Interactive は、文字列 csv の値とその長さを表示します。次に例を示します。
07/10/2009, 3.32 07/13/2009, 3.38 07/14/2009, 3.50 07/15/2009, 3.63 " > csv.Length;; val it : int = 224513
次の図は、[F# Interactive] ウィンドウを示しています。
[F# Interactive] ウィンドウ
次に、F# コードを記述して CSV (コンマ区切り値) データを解析します。 CSV ファイルという名前は、コンマで区切られた値を含んでいることに由来します。 コード エディターで、次のコードを追加します。 各行を追加しているとき、このセクションで追加したコードをその行まで選択し、Alt キーを押しながら Enter キーを押すと、部分的な結果を確認できます。 次の点に注意してください。
複雑な入れ子になった式の途中でも、ピリオドを入力すると、IntelliSense によって役立つ情報が表示されます。
コードが不完全である (または正しくない) 場合は、コード内の構文エラーとセマンティック エラーが赤い波線で指摘されます。
パイプ演算子 (|>) を使用して、パイプラインを作成します。 パイプ演算子は、ある式からの戻り値を受け取り、次の行にある関数の引数として使用します。 パイプラインと F# Interactive によって、データ処理コードの部分的な実行が簡単になります。
let interest = csv.Split([|'\n'|]) |> Seq.skip 8 |> Seq.map (fun line -> line.Trim()) |> Seq.filter (fun line -> not (line.EndsWith("ND"))) |> Seq.filter (fun line -> not (line.Length = 0)) |> Seq.map (fun line -> line.Split([|','|])) |> Seq.map ( fun values -> System.DateTime.Parse(values.[0]), float values.[1])
ここで、この機能に名前を付けます。 url の定義から 10 を削除し、「%d」に置き換えることで、リテラル文字列を書式指定文字列に変更します。 この書式指定文字列の後ろに「maturity」を追加します。 この新しい行を除くすべてのコードを選択し、Tab キーを押します。 インデントが設定されたコード ブロックの上に、「let loadRates maturity =」を追加します。 インデントが設定されたコード ブロックの末尾に、「interest」を追加します。 次の点に注意してください。
F# では、インデントが重要な意味を持ちます。 インデントは、入れ子レベルを示します。
Tab キーは、メソッドの抽出リファクタリング (C#) のような役割を果たします。
コードは次のようになります。
open System.Net open System.IO let loadRates maturity = let url = sprintf "http://www.federalreserve.gov/releases/h15/data/business_day/H15_TCMNOM_Y%d.txt" maturity let req = WebRequest.Create(url, Timeout = 10000000) let resp = req.GetResponse() let stream = resp.GetResponseStream() let reader = new StreamReader(stream) let csv = reader.ReadToEnd() let interest = csv.Split([|'\n'|]) |> Seq.skip 8 |> Seq.map (fun line -> line.Trim()) |> Seq.filter (fun line -> not (line.EndsWith("ND"))) |> Seq.filter (fun line -> not (line.Length = 0)) |> Seq.map (fun line -> line.Split([|','|])) |> Seq.map ( fun values -> System.DateTime.Parse(values.[0]), float values.[1]) interest
この機能を新しい入力に対して使用します。 すべてのコードを選択し、Alt キーを押しながら Enter キーを押して、F# Interactive でコードを実行します。 F# Interactive プロンプトで、他の満期金利 (1、2、5) について、新しい loadRates 関数を呼び出します。 次の点に注意してください。
F# Interactive では、以前の定義は失われませんが、新しい定義が有効になります。
複雑に構造化されたデータが、特別な出力機能によってレンダリングされます。
F# を使用してコンポーネントを開発するには
作成した機能を公開するライブラリ プロジェクトを作成します。 [ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。 [新しいプロジェクト] ダイアログ ボックスで、[インストールされたテンプレート] の [Visual F#] を選択し、[F# ライブラリ] を選択して、新しいライブラリ プロジェクトを作成します。 プロジェクトに「RateAnalysis」という名前を付けます。 以前に作成したコードを RateAnalysis.fsx からコピーし、Module1.fs に貼り付けます。 Module1.fs でのモジュール宣言を、モジュール Module1 からモジュール RateLoader に変更します。 ソリューション エクスプローラーで、Module1.fs の名前を RateLoader.fs に変更します。 次の点に注意してください。
- 既定の F# ライブラリ テンプレートには、拡張子が .fs のコード ファイルと、拡張子が .fsx のスクリプトが含まれています。 このスクリプト ファイルを使用すると、ライブラリ コードを対話形式でテストできます。
次の図は、F# で利用できるいくつかのオプションが表示された [新しいプロジェクト] ダイアログ ボックスを示しています。 [F# ライブラリ] プロジェクト テンプレートが選択されています。
F# テンプレート オプション
必要な機能を公開する F# クラスを作成します。 ソリューション エクスプローラーで、プロジェクトを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。 [新しい項目の追加] ダイアログ ボックスで、[F# ソース ファイル] を選択します。 ファイルに「Analyzer.fs」という名前を付けます。 ソリューション エクスプローラーで Script.fsx を右クリックし、[下へ移動] をクリックします (または、Alt キーを押しながら↓キーを押します)。 次のコードを Analyzer.fs に貼り付けます。
module RateAnalysis.Analyzer open RateLoader /// Provides analysis of historical interest rate data. type Analyzer(ratesAndDates) = let rates = ratesAndDates |> Seq.map snd /// Construct Analyzer objects for each maturity category. static member GetAnalyzers(maturities) = maturities |> Seq.map loadRates |> Seq.map (fun ratesAndDates -> new Analyzer(ratesAndDates)) member sa.Min = let date, minRate = (Seq.minBy (fun (_, rate) -> rate) ratesAndDates) (minRate, date.ToString("d")) member sa.Max = let date, maxRate = (Seq.maxBy (fun (_, rate) -> rate) ratesAndDates) (maxRate, date.ToString("d")) member sa.Current = rates |> List.ofSeq |> List.rev |> List.head
次の点に注意してください。
次に、XML ドキュメント コメントを生成します。 ソリューション エクスプローラーで、プロジェクトを右クリックし、[プロパティ] をクリックします。 [ビルド] タブで、ページの下部にある [XML ドキュメント ファイル] チェック ボックスをオンにします。 次の点に注意してください。
どの F# アセンブリでも XML ドキュメントを生成できます。
既定では、XML ドキュメントは出力パスに生成されます。
プロジェクトをビルドするために、Ctrl キーと Shift キーを押しながら B キーを押すか、または F6 キーを押します。 次の点に注意してください。
プロジェクトが正常にビルドされます。
[エラー一覧] ウィンドウには、エラーは表示されません。
出力ディレクトリには、.dll、.pdb、および .xml の各ファイルが作成されます。
[出力] ウィンドウには、次のような出力が表示されます。
------ Build started: Project: RateAnalysis, Configuration: Debug Any CPU ------ C:\Program Files (x86)\Microsoft F#\v4.0\fsc.exe -o:obj\Debug\RateAnalysis.exe -g --debug:full --noframework --define:DEBUG --define:TRACE --optimize- --tailcalls- -r:"C:\Program Files (x86)\Microsoft F#\v4.0\FSharp.Core.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" -r:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" --target:exe --warn:3 --warnaserror:76 --vserrors --utf8output --fullpaths --flaterrors Program.fs RateLoader.fs ValueAnalyzer.fs RateAnalysis -> C:\Users\ghogen\Documents\Visual Studio 10\Projects\RateAnalysis\RateAnalysis\bin\Debug\RateAnalysis.exe ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
C# クライアント アプリケーションを追加するために、ソリューション ノードを右クリックし、[追加] をポイントして、[新しいプロジェクト] をクリックします。 [新しいプロジェクト] ダイアログ ボックスで、[インストールされたテンプレート] の [Visual C#] を選択し、[コンソール アプリケーション] を選択します。 [他の言語] ノードを展開する必要がある場合があります。 プロジェクトに「CSharpDriver」という名前を付けます。 プロジェクトの [参照設定] ノードを右クリックし、[参照の追加] をクリックします。 [参照の追加] ダイアログ ボックスの [プロジェクト] タブで、[RateAnalysis] を選択し、[OK] をクリックします。 [CSharpDriver] プロジェクト ノードを右クリックし、[スタートアップ プロジェクトに設定] をクリックします。 C# アプリケーションの Main メソッドの本体に、次のコードを入力します。 次の点に注意してください。
C# と F# の間で、プロジェクト間参照を追加できます。
F# で定義された名前空間と型は、C# で他の型と同じように使用できます。
F# のドキュメント コメントを C# の IntelliSense で参照できます。
F# API からの組の戻り値に C# でアクセスできます。 組は .NET Framework 4 の Tuple 値です。
var maturities = new[] { 1, 2, 5, 10 }; var analyzers = RateAnalysis.Analyzer.Analyzer.GetAnalyzers(maturities); foreach (var item in analyzers) { Console.WriteLine("Min = {0}, \t Max = {1}, \t Current = {2}", item.Min, item.Max, item.Current); } Console.WriteLine("Press Enter to exit."); Console.ReadLine();
アプリケーションをデバッグするために、F11 キーを押してアプリケーションをビルドし、デバッガーでアプリケーションを起動して、実行されるコードの最初の行にステップ インします。 F# コードの GetAnalyzers メンバーの本体にステップ インするまで、F11 キーを数回押します。 次の点に注意してください。
C# コードから F# コードに簡単にステップ インできます。
F# の各式は、デバッガーでの 1 つのステップに相当します。
[ローカル] ウィンドウに maturities の値が表示されます。
引き続き F11 キーを押していくと、アプリケーションの残りの部分がステップ実行されます。
[カーソル行の前まで実行]、[次のステートメントの設定]、[ブレークポイントの挿入]、[ウォッチ式の追加]、[逆アセンブルを表示] など、デバッガー コマンドはすべて期待どおりに機能します。
F# アプリケーションを配置するには
この手順では、別のバージョンの .NET Framework を対象とするプロジェクトを設定します。 ソリューション エクスプローラーで、F# RateAnalysis プロジェクトを右クリックし、[プロパティ] をクリックします。 [アプリケーション] タブで、[ターゲット フレームワーク] 設定を .NET Framework 3.5 に変更します。 次の点に注意してください。
F# では、異なるバージョンの .NET Framework を対象とすることができます。
対象の .NET Framework を変更するには、プロジェクトを再読み込みする必要があります。
対象の .NET Framework を変更すると、[参照の追加] ダイアログ ボックスの一部のアセンブリ参照が無効になり、使用できなくなります。
C# プロジェクトでは、.NET Framework 2.0 を対象とするバージョンの FSharp.Core アセンブリへの参照を追加する必要があります。このアセンブリは、バージョン 3.0 と 3.5 の .NET Framework を対象とする場合にも使用する必要があります。 ソリューション エクスプローラーで、[参照設定] ノードを右クリックし、[参照の追加] をクリックします。 [.NET] タブで、FSharp.Core Version 2.0.0.0 を選択し、[OK] をクリックします。 ソリューションをビルドし直します。
必須コンポーネントを設定するために、CSharpDriver の [プロパティ] ノードをダブルクリックします。 [発行] タブの [必須コンポーネント] ボタンをクリックし、[必須コンポーネント] ダイアログ ボックスで、[Microsoft Visual F# Runtime for .NET 2.0] チェック ボックスをオンにします。 次の点に注意してください。
F# には、.NET Framework とは別のランタイム パッケージがあります。
このランタイム パッケージは、F# を使用するアプリケーションを配置するときに、必須コンポーネントとして明示的に追加する必要があります。
ランタイム パッケージには、.NET Framework 2.0、3.0、および 3.5 に対応するバージョン 2.0 と、.NET Framework 4 に対応するバージョン 4.0 の 2 つがあります。
ClickOnce を使用して C# アプリケーションを配置します。 CSharpDriver プロジェクトを右クリックし、[発行] をクリックします。 発行ウィザードで、[完了] をクリックします。 作成された CSharpDriver アプリケーションを実行します。 次の点に注意してください。
アプリケーションには Visual F# ランタイム パッケージが含まれています。
アプリケーションを実行すると、F# ランタイム パッケージがインストールされ、アプリケーションが正常に実行されます。
次の手順
F# コードを書き始めるには、「チュートリアル: 初めての F# プログラム」を参照してください。F# の関数について学習するには、「ファースト クラスの値としての関数 (F#)」を参照してください。 F# 言語について調べるには、「F# 言語リファレンス」を参照してください。