Tutorial: Utilizar Visual F# para crear, depurar e implementar una aplicación

En este tutorial se presenta cómo utilizar F# en Visual Studio junto con .NET Framework 4.5.

En este tutorial, se empezará a usar Visual Studio para escribir aplicaciones en F# tomando como ejemplo un análisis histórico de datos de tasas de interés de la Tesorería de Estados Unidos.Comenzará con un análisis rápido de los datos utilizando la ventana interactiva de F#; después, escribirá y probará código para analizar los datos, y finalmente agregará un front-end de C# para explorar la integración del código de F# con otros lenguajes de .NET.

Requisitos previos

Necesita los componentes siguientes para completar este tutorial:

  • Visual Studio

[!NOTA]

Es posible que su equipo muestre nombres o ubicaciones diferentes para algunos de los elementos de la interfaz de usuario de Visual Studio incluidos en las instrucciones siguientes. La edición de Visual Studio que se tenga y la configuración que se utilice determinan estos elementos. Para obtener más información, vea Valores de configuración de Visual Studio.

Para crear un script de F#

  1. Primero, cree un script de F#.En el menú Archivo, elija Nuevo y, a continuación, haga clic en Archivo.En el cuadro de diálogo Nuevo archivo, seleccione Script en la categoría General bajo la lista de plantillas de Instalado y seleccione Archivo de script de F#.Haga clic en Abrir para crear el archivo y, a continuación, guarde el archivo como RateAnalysis.fsx.

  2. Utilice las API de .NET y F# para tener acceso a los datos del sitio de Internet de la Reserva Federal de Estados Unidos.Escriba el código siguiente.

    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()
    

    Tenga en cuenta lo siguiente:

    • Se colorean las cadenas y palabras clave.

    • Las listas de finalización aparecen después de escribir cada punto (.).

    • Puede tener nombres de método completos y otros identificadores de Visual Studio utilizando el método abreviado de teclado CTRL+ESPACIO o CTRL+J en el medio de un identificador.Una lista de finalización aparece cuando se usa CTRL+J.

    • Cuando se deja el puntero del mouse sobre un identificador en el código, se puede ver una información sobre herramientas que contiene información sobre ese identificador.

    • Si presiona F1 cuando el cursor está en WebRequest, aparece la documentación esperada.

    • Si presiona F1 cuando el cursor está en let, aparece la documentación esperada.

    • De manera predeterminada, se hace referencia a los tipos y espacios de nombres de mscorlib.dll, System.dll y System.Windows.Forms.dll.

    • El valor Timeout que se establece aquí es una propiedad, no un argumento de constructor.F# permite establecer los valores de propiedad de esta manera.

    • Si copia la dirección URL del ejemplo en un explorador, recibirá una lista de valores separados por comas que contienen fechas y tasas de interés, publicada por la Reserva Federal de Estados Unidos.

  3. Ahora ejecutará el código con F# Interactive.Seleccione todo el código (con el mouse o presionando CTRL+A) y haga clic con el botón secundario en Ejecutar de manera interactiva.(Asimismo, puede presionar las teclas ALT+ENTRAR).

    • Si aún no esta visible, aparecerá la ventana de F# Interactive.

    • El código se ejecuta correctamente.

    • En la ventana de F# Interactive aparece lo siguiente.

      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. A continuación, inspeccione los datos utilizando F# Interactive.En el símbolo del sistema de F# Interactive, escriba csv;; y presione ENTRAR.Escriba csv.Length;; y presione ENTRAR.Tenga en cuenta lo siguiente:

    • Los datos son actuales.

    • F# Interactive muestra el valor de la cadena csv y su longitud, como se muestra aquí.

      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
      
    • La siguiente ilustración muestra la ventana de F# Interactive.

      Ventana de F# Interactive

      Ventana de F# Interactive

  5. Ahora escribirá código de F# para analizar los datos del archivo .csv (valores separados por comas).Así se denomina un archivo CSV porque contiene los valores separado por comas.En el editor de código, agregue el código siguiente.Además, agregue open System.Globalization en la parte superior del archivo.Según agrega cada línea, seleccione el código agregado en esta sección hasta esa línea y presione ALT+ENTER para ver los resultados parciales.Tenga en cuenta lo siguiente:

    • IntelliSense le ofrece información útil después de escribir un punto, incluso en medio de complejas expresiones anidadas.

    • Cuando el código está incompleto (o incorrecto), los subrayado ondulados rojos indican que contiene errores sintácticos y semánticos.

    • Las canalizaciones se crean con al operador de canalización (|>).El operador de canalización toma el valor devuelto de una expresión y lo usa como argumento para la función de la línea siguiente.Las canalizaciones y F# Interactive permiten una ejecución parcial de una línea del código de procesamiento de datos.

    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. Ahora dará un nombre a esta funcionalidad.Elimine el identificador de las series bcb44e57fb57efbe90002369321bfb3f de la definición de url y reemplácelo por %s para convertir el literal de cadena en una cadena de formato.Agregue seriesID después de la cadena de formato.Seleccione todo el código excepto las directivas de apertura y presione Tabulador.Agregue las siguientes líneas de código por encima del bloque de código sangrado.

    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
    

    Al final del bloque de código con sangría, agregue interest.Tenga en cuenta lo siguiente:

    El código tendrá una apariencia similar a la siguiente.

    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. Ahora utilizará esta funcionalidad en nuevas entradas.Seleccione todo el código y presione ALT+ENTER para ejecutarlo con F# Interactive.En el indicador de F# Interactive, llame a la nueva función loadRates en otras tasas de vencimiento: 1, 2 y 5, en años.Tenga en cuenta lo siguiente:

    • Las definiciones anteriores no se pierden en F# Interactive, pero se dispone de nuevas definiciones.

    • Los datos estructurados complejos se presentan mediante una funcionalidad de impresión especial.

Para desarrollar un componente con F#

  • Cree un proyecto de biblioteca para exponer la funcionalidad que ha creado.En el menú Archivo, elija Nuevo y haga clic en Proyecto.En el cuadro de diálogo Nuevo proyecto, seleccione Visual F# en la lista Instalado y, a continuación, en Biblioteca de F# para crear un nuevo proyecto de biblioteca.Asigne al proyecto el nombre RateAnalysis.Copie el código que creó previamente de RateAnalysis.fsx y péguelo en Library1.fs.Agregue una declaración de módulo en la parte superior del archivo: module RateLoader.En Explorador de soluciones, cambie el nombre Library1.fs a RateLoader.fs y guarde el archivo.Tenga en cuenta lo siguiente:

    • La plantilla Biblioteca de F# proporciona un archivo de código con la extensión.fs y un script con la extensión .fsx.Puede utilizar el archivo de script para probar el código de la biblioteca interactivamente.
  1. Ahora creará una clase de F# que expone la funcionalidad deseada.En el Explorador de soluciones, haga clic en el proyecto con el botón secundario, seleccione Agregar y, a continuación haga clic en Nuevo elemento.En el cuadro de diálogo Agregar nuevo elemento, seleccione la categoría Archivo de código fuente de F#.Denomine el archivo Analyzer.fs.Haga clic con el botón secundario en Script.fsx en el Explorador de soluciones y, a continuación, haga clic en Bajar.O bien, presione ALT+FLECHA ABAJO. Pegue el código siguiente en 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 
    

    Tenga en cuenta lo siguiente:

    • F# admite los conceptos de la programación orientada a objetos.Para obtener más información, vea Clases (F#), Herencia (F#) y otros temas pertinentes en la Referencia del lenguaje F#.
  2. Para compilar el proyecto, presione Ctrl+Mayús+B o F6.Tenga en cuenta lo siguiente:

    • El proyecto se compila correctamente.

    • La ventana Lista de errores no muestra ningún error.

    • El directorio de salida contiene archivos .dll, .pdb y .xml.

    • La Ventana de salida muestra el siguiente resultado:

      ------ 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. Para agregar una aplicación cliente de C#, abra el acceso directo del nodo de la solución, elija Agregar y elija Nuevo proyecto.En el cuadro de diálogo Agregar nuevo proyecto, seleccione Visual C# en la lista Plantillas instaladas y, a continuación, seleccione Aplicación de consola.Puede necesitar expandir el nodo Otros lenguajes.Denomine al proyecto CSharpDriver y haga clic en el botón Aceptar.Abra el acceso directo del nodo Referencias de este proyecto y, a continuación, seleccione Agregar referencia.Elija el nodo Solución y, a continuación, elija el nodo Proyectos.Active la casilla de verificación situada junto al proyecto RateAnalysis y, después, elija el botón Aceptar.Abra el acceso directo del nodo del proyecto CSharpDriver y haga clic en Establecer como proyecto de inicio.Escriba el siguiente código en el cuerpo del método Main de la aplicación de C#.

    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();
    

    Tenga en cuenta lo siguiente:

    • Puede agregar referencias proyecto a proyecto a y de C# y F#.

    • Los espacios de nombres y los tipos definidos de F# se pueden utilizar en C# como cualquier otro tipo.

    • Los comentarios de documentación de F# están disponibles en C# IntelliSense.

    • C# tiene acceso a los valores devueltos de tupla de la API de F#.Las tuplas son valores Tuple en .NET Framework 4.5

  4. Para depurar la aplicación, presione F11 para compilar la aplicación, inicie la aplicación en el depurador y recorra la primera línea de código ejecutado.Presione F11 varias veces más hasta llegar al código de F# del miembro GetAnalyzers.Tenga en cuenta lo siguiente:

    • Puede pasar con facilidad del código de C# al código de F#.

    • Cada expresión de F# es un paso en el depurador.

    • La ventana Locales muestra los valores de maturities.

    • Si se sigue presionando F11, se evalúa el resto de la aplicación.

    • Los comandos del depurador como Ejecutar hasta el cursor, Establecer instrucción siguiente, Insertar punto de interrupción, Agregar inspección e Ir al desensamblado funcionan como se espera.

Para implementar la aplicación

  1. Si todavía se está depurando, detenga la depuración presionando las teclas SHIFT + F5 o abra el menú Depurar y seleccione Detener depuración.

  2. Abra el acceso directo del proyecto CSharpDriver y, a continuación, seleccione Propiedades.

  3. En el diseñador de proyectos, elija la pestaña Publicar, la cual muestra opciones para implementar la aplicación.

  4. Elija el botón Asistente para publicación.

    El Asistente para publicación se inicia y la primera pantalla pregunta dónde desea que se ubiquen los archivos publicados.

  5. En el cuadro de texto, especifique una ubicación de archivo en el disco local donde desea que los archivos de instalación para la aplicación estén ubicados cuando publique o elija el botón Examinar para navegar hasta una ubicación.

  6. Haga clic en el botón Finalizar para aceptar todos los valores predeterminados para compilar una instalación estándar que se puede distribuir a equipos cliente, o haga clic en el botón Siguiente para ver otras opciones de publicación.

    Una aplicación ejecutable de instalación y los archivos auxiliares se publican en la ubicación especificada.

Pasos siguientes

Aprenda los conceptos básicos de la escritura de código de F# en Tutorial: Implementar el primer programa en F#; encuentre información sobre las funciones de F# en Funciones como valores de primera clase (F#).Puede explorar el lenguaje F# leyendo Referencia del lenguaje F#.

Vea también

Otros recursos

Tutoriales y ejemplos de Visual F#

Tutoriales y ejemplos de Visual F#