チュートリアル: Visual F# を使用したアプリケーションの作成、デバッグ、および配置
このチュートリアルでは、Visual Studio で .NET Framework 4.5 と共に F# を使用する手順を紹介します。
このチュートリアルでは、米国財務省の金利情報に関するこれまでのデータ分析を例に挙げながら、Visual Studio を使用して F# アプリケーションを記述する方法を説明します。まず F# の対話形式のウィンドウを使用して簡単な分析を行い、次にデータを分析するコードを記述してテストします。その後、C# のフロントエンドを追加して、作成した F# コードを他の .NET 言語と統合する方法を示します。
必須コンポーネント
このチュートリアルを実行するには、次のコンポーネントが必要です。
- Visual Studio
[!メモ]
お使いのマシンで、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/datadownload/Output.aspx?rel=H15&series=bcb44e57fb57efbe90002369321bfb3f&lastObs=&from=&to=&filetype=csv&label=include&layout=seriescolumn" 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 キーを押します)、右クリックして、[対話形式で実行] をクリックします。(または、Alt + Enter キーを押します)。
[F# Interactive] ウィンドウがまだ表示されていない場合は、表示されます。
コードが正常に実行されます。
[F# Interactive] ウィンドウに次の結果が表示されます。
val url : string = "http://www.federalreserve.gov/datadownload/Output.aspx?rel=H1"+[107 chars] val req : System.Net.WebRequest val resp : System.Net.WebResponse val stream : System.IO.Stream val reader : System.IO.StreamReader val csv : string = ""Series Description","Market yield on U.S. Treasury securities"+[224219 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 ファイルという名前は、コンマで区切られた値を含んでいることに由来します。コード エディターで、次のコードを追加します。また、ファイルの先頭に「open System.Globalization」を追加します。各行を追加しているとき、このセクションで追加したコードをその行まで選択し、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], CultureInfo.CreateSpecificCulture("en-US")), float values.[1])
ここで、この機能に名前を付けます。url の定義からシリーズ ID bcb44e57fb57efbe90002369321bfb3f を削除し、「%s」に置き換えることで、リテラル文字列を書式指定文字列に変更します。この書式指定文字列の後に「seriesID」を追加します。open ディレクティブを除くすべてのコードを選択し、Tab キーを押します。インデントが設定されたコード ブロックの上に以下のコード行を追加します。
let loadRates maturity = // The following tuples associate various maturity durations, in years, // with codes defined for treasury bills by the Federal Reserve. let maturitiesMap = Map.ofList [(1, "e30653a4b627e9d1f2490a0277d9f1ac") (2, "c66ea77a2e8f0919c5133c7633065908") (5, "fbb02942bfdbff31a479e98bcbe26388") (10, "bcb44e57fb57efbe90002369321bfb3f") (20, "a1ebeb6e84ca6389772dd054dc980191")] let seriesID = Map.find maturity maturitiesMap
インデントが設定されたコード ブロックの末尾に、「interest」を追加します。次の点に注意してください。
F# では、インデントが重要な意味を持ちます。インデントは、入れ子レベルを示します。
Tab キーは、メソッドの抽出リファクタリング (C#) のような役割を果たします。
コードは次のようになります。
open System.Net open System.IO let loadRates maturity = // The following tuples associate various maturity durations, in years, // with codes defined for treasury bills by the Federal Reserve. let maturitiesMap = Map.ofList [(1, "e30653a4b627e9d1f2490a0277d9f1ac") (2, "c66ea77a2e8f0919c5133c7633065908") (5, "fbb02942bfdbff31a479e98bcbe26388") (10, "bcb44e57fb57efbe90002369321bfb3f") (20, "a1ebeb6e84ca6389772dd054dc980191")] let seriesID = Map.find maturity maturitiesMap let url = sprintf "http://www.federalreserve.gov/datadownload/Output.aspx?rel=H15&series=%s&lastObs=&from=&to=&filetype=csv&label=include&layout=seriescolumn" seriesID 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], CultureInfo.CreateSpecificCulture("en-US")), float values.[1]) interest
この機能を新しい入力に対して使用します。すべてのコードを選択し、Alt キーを押しながら Enter キーを押して、F# Interactive でコードを実行します。F# Interactive プロンプトで、他の満期金利 (1、2、5) について、新しい loadRates 関数を呼び出します。次の点に注意してください。
F# Interactive では、以前の定義は失われませんが、新しい定義が有効になります。
複雑に構造化されたデータが、特別な出力機能によってレンダリングされます。
F# を使用してコンポーネントを開発するには
作成した機能を公開するライブラリ プロジェクトを作成します。[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。[新しいプロジェクト] ダイアログ ボックスで、[インストール済み] の一覧の [Visual F#] をクリックし、[F# ライブラリ] を選択して、新しいライブラリ プロジェクトを作成します。プロジェクトに「RateAnalysis」という名前を付けます。以前に作成したコードを RateAnalysis.fsx からコピーし、Library1.fs に貼り付けます。ファイルの先頭にモジュール宣言 module RateLoader を追加します。ソリューション エクスプローラーで、Library1.fs の名前を RateLoader.fs に変更し、ファイルを保存します。次の点に注意してください。
- 既定の F# ライブラリ テンプレートには、拡張子が .fs のコード ファイルと、拡張子が .fsx のスクリプトが含まれています。このスクリプト ファイルを使用すると、ライブラリ コードを対話形式でテストできます。
必要な機能を公開する 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
次の点に注意してください。
プロジェクトをビルドするために、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」という名前を付け、[OK] をクリックします。このプロジェクトの [参照] ノードでショートカット メニューを開き、[参照の追加] をクリックします。[ソリューション] ノードを選択し、[プロジェクト] ノードを選択します。[RateAnalysis] プロジェクトの横にあるチェック ボックスをオンにし、[OK] をクリックします。[CSharpDriver] プロジェクト ノードのショートカット メニューを開き、[スタートアップ プロジェクトに設定] をクリックします。C# アプリケーションの Main メソッドの本体に、次のコードを入力します。
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();
次の点に注意してください。
C# と F# の間で、プロジェクト間参照を追加できます。
F# で定義された名前空間と型は、C# で他の型と同じように使用できます。
F# のドキュメント コメントを C# の IntelliSense で参照できます。
F# API からのタプルの戻り値に C# でアクセスできます。タプルは、.NET Framework 4.5 の Tuple 値です。
アプリケーションをデバッグするために、F11 キーを押してアプリケーションをビルドし、デバッガーでアプリケーションを起動して、実行されるコードの最初の行にステップ インします。F# コードの GetAnalyzers メンバーの本体にステップ インするまで、F11 キーを数回押します。次の点に注意してください。
C# コードから F# コードに簡単にステップ インできます。
F# の各式は、デバッガーでの 1 つのステップに相当します。
[ローカル] ウィンドウに maturities の値が表示されます。
引き続き F11 キーを押していくと、アプリケーションの残りの部分がステップ実行されます。
[カーソル行の前まで実行]、[次のステートメントの設定]、[ブレークポイントの挿入]、[ウォッチ式の追加]、[逆アセンブルを表示] など、デバッガー コマンドはすべて期待どおりに機能します。
アプリケーションを配置するには
デバッグ中の場合は、Shift キーを押しながら F5 キーを押すか [デバッグ] メニューの [デバッグの停止] をクリックして、デバッグを停止します。
CSharpDriver プロジェクトのショートカット メニューを開き、[プロパティ] をクリックします。
プロジェクト デザイナーで、[発行] タブをクリックします。アプリケーションを配置するためのオプションが表示されます。
[発行ウィザード] をクリックします。
発行ウィザードが起動し、最初の画面で、発行されるファイルの配置場所を指定するよう求められます。
テキスト ボックスで、発行時にアプリケーションのインストール ファイルを配置する場所としてローカル ディスク上の場所を指定するか、[参照] をクリックしてその場所に移動します。
すべての既定値をそのまま使用して、クライアント コンピューターに配布される標準的なセットアップをビルドするには [完了] をクリックし、他の発行オプションを表示するには [次へ] をクリックします。
セットアップ実行可能ファイルと関連ファイルは、指定した場所に発行されます。
次の手順
F# コードを書き始めるには、「チュートリアル: 初めての F# プログラム」を参照してください。F# の関数について学習するには、「ファースト クラスの値としての関数 (F#)」を参照してください。F# 言語について調べるには、「F# 言語リファレンス」を参照してください。