逐步解說:使用 Visual F# 建立、偵錯和部署應用程式
這個逐步解說簡介您在 Visual Studio 中搭配使用 F# 和 .NET Framework 4 的經驗。
在這個逐步解說中,您將學習如何透過美國財政部利率資料的歷史分析範例,開始使用 Visual Studio 撰寫 F# 應用程式。 您將從使用 F# Interactive 視窗進行一些資料快速分析著手,然後撰寫及測試一些程式碼來分析資料,接著加入 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()
請注意以下幾點:
會以顏色標示字串和關鍵字。
在您輸入每一個句號 (.) 之後,完成清單隨即出現。
您可以在識別項的中間使用按鍵盤快速鍵 CTRL+SPACE 或 CTRL+J,以取得 Visual Studio 完整方法名稱和其他識別項。 當您使用 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/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 的定義中移除 bcb44e57fb57efbe90002369321bfb3f 並以 %s 取代,讓字串常值變成格式字串。 在格式字串之後加入 seriesID。 全選除了開啟指示詞外的程式碼,然後按 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 提示中,於其他到期利率上呼叫新的 loadRates 函式:1、2 和 5 (以年為單位)。 請注意以下幾點:
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,並點選確定。 開啟專案 參考 的快顯功能表,然後選擇 加入參考。 選擇方案 節點,然後選擇專案 節點。 選取RateAnalysis 專案旁的核取方塊,然後選取確定 。 以滑鼠右鍵按一下 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# 之間加入專案對專案間參考。
就像任何其他類型一樣,可以從 C# 使用 F# 定義的命名空間和類型。
在 C# IntelliSense 中可以使用 F# 文件註解。
C# 可以從 F# API 存取 Tuple 傳回值。 Tuple 就是 .NET Framework 4 Tuple 值。
若要對應用程式進行偵錯,請按 F11 以建置應用程式,在偵錯工具中啟動應用程式,然後逐步執行至已執行程式碼的第一行。 按 F11 數次,直到您逐步執行至 GetAnalyzers 成員主體中的 F# 程式碼。 請注意以下幾點:
您可以輕易地從 C# 程式碼逐步執行至 F# 程式碼。
F# 中的每一個運算式都是偵錯工具中的一個步驟。
[區域變數] 視窗會顯示 maturities 的值。
繼續按 F11 逐步完成其餘的應用程式評估。
[執行至游標處]、[設定下一個陳述式]、[插入中斷點]、[加入監看式] 和 [移至反組譯碼] 等偵錯工具命令全都如預期運作。
部署應用程式
如果您要停止偵錯,可以利用按SHIFT + F5或是選擇偵錯 功能表中的停止偵錯 。
開啟資料夾的捷徑功能表,然後選取 屬性。
在專案設計工具中,選擇發行 索引標籤以顯示部屬您app的選項。
選取 發行精靈 。
發行精靈啟動後,第一個畫面將會詢問發行檔案放置的位置。
在文字方塊中,指定檔案位置在要安裝應用程式的檔案可以將您的本機磁碟上,在發行時,或選取 瀏覽 按鈕巡覽至某個位置。
選取 完成 按鈕接收所有預設為可能散發至用戶端的標準安裝,或選擇 下一個 按鈕來檢視其他發行選項。
設定可執行檔和支援檔案發行至您指定的位置。
後續步驟
請閱讀 逐步解說:您的第一個 F# 程式以便開始撰寫 F# 程式碼,或是閱讀當做優先使用值的函式 (F#)以了解 F# 中的函式。 您可以閱讀 F# 語言參考以探索 F# 語言。