共用方式為


逐步解說:使用 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# 指令碼

  1. 首先,建立 F# 指令碼。在 [檔案] 功能表上指向 [新增],然後按一下 [檔案]。在 新增檔案 對話方塊中,選取 已安裝的範本 清單中的 一般中的 指令碼,然後選取 F# 指令碼檔案按一下 [開啟] 以建立檔案,然後將檔案儲存為 [RateAnalysis.fsx]。

  2. 使用 .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 複製到瀏覽器中,則會取得一份以逗號分隔的值清單,內含美國聯邦準備理事會所宣佈的日期和利率。

  3. 您現在將使用 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]
      
      >
      
  4. 接下來,使用 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# Interactive 視窗

  5. 您現在將撰寫 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])
    
  6. 您現在將為這項功能命名。從 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。請注意以下幾點:

    此程式碼現在與下列程式碼相似:

    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
    
  7. 您現在將在新的輸入上使用這項功能。選取所有程式碼並且按 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)。您可以使用指令碼檔案,以互動方式測試程式庫程式碼。
  1. 您現在將建立 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 
    

    請注意以下幾點:

    • F# 支援物件導向程式設計概念。如需詳細資訊,請參閱 F# 語言參考中的 類別 (F#)繼承 (F#) 和其他相關主題。
  2. 若要建置專案,請按 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 ==========
      
  3. 若要加入 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 值。

  4. 若要對應用程式進行偵錯,請按 F11 以建置應用程式,在偵錯工具中啟動應用程式,然後逐步執行至已執行程式碼的第一行。按 F11 數次,直到您逐步執行至 GetAnalyzers 成員主體中的 F# 程式碼。請注意以下幾點:

    • 您可以輕易地從 C# 程式碼逐步執行至 F# 程式碼。

    • F# 中的每一個運算式都是偵錯工具中的一個步驟。

    • [區域變數] 視窗會顯示 maturities 的值。

    • 繼續按 F11 逐步完成其餘的應用程式評估。

    • [執行至游標處]、[設定下一個陳述式]、[插入中斷點]、[加入監看式] 和 [移至反組譯碼] 等偵錯工具命令全都如預期運作。

部署應用程式

  1. 如果您要停止偵錯,可以利用按SHIFT + F5或是選擇偵錯 功能表中的停止偵錯

  2. 開啟資料夾的捷徑功能表,然後選取 屬性

  3. 在專案設計工具中,選擇發行 索引標籤以顯示部屬您app的選項。

  4. 選取 發行精靈

    發行精靈啟動後,第一個畫面將會詢問發行檔案放置的位置。

  5. 在文字方塊中,指定檔案位置在要安裝應用程式的檔案可以將您的本機磁碟上,在發行時,或選取 瀏覽 按鈕巡覽至某個位置。

  6. 選取 完成 按鈕接收所有預設為可能散發至用戶端的標準安裝,或選擇 下一個 按鈕來檢視其他發行選項。

    設定可執行檔和支援檔案發行至您指定的位置。

後續步驟

請閱讀 逐步解說:您的第一個 F# 程式以便開始撰寫 F# 程式碼,或是閱讀當做優先使用值的函式 (F#)以了解 F# 中的函式。您可以閱讀 F# 語言參考以探索 F# 語言。

請參閱

其他資源

Visual F# 範例與逐步解說

Visual F# 範例與逐步解說