F Sharp (linguagem de programação) - F Sharp (programming language)

F #
F Sharp logo.svg
Logomarca F #
Paradigma Multi-paradigma : funcional , imperativo , orientado a objetos , metaprogramação , reflexivo , concorrente
Família ML
Projetado por Don Syme , Microsoft Research
Desenvolvedor Microsoft , The F # Software Foundation
Apareceu pela primeira vez 2005 ; 16 anos atrás , versão 1.0 ( 2005 )
Versão estável
5.0  Edite isso no Wikidata / 10 de novembro de 2020 ; 11 meses atrás ( 10 de novembro de 2020 )
Versão de visualização
Versão 5.0 / 2 de abril de 2019 ; 2 anos atrás ( 02/04/2019 )
Disciplina de digitação Estático , forte , inferido
SO Plataforma cruzada : .NET , .NET Framework , Mono
Licença Licença MIT
Extensões de nome de arquivo .fs, .fsi, .fsx, .fsscript
Local na rede Internet fsharp .org
Influenciado por
C # , Erlang , Haskell , ML , OCaml , Python , Scala
Influenciado
C # , Elm , F * , LiveScript

F # (pronuncia-se F sustenido ) é uma linguagem de programação funcional , de propósito geral, fortemente tipada e multiparadigma , que abrange métodos de programação funcionais , imperativos e orientados a objetos . F # é mais frequentemente usado como uma linguagem de plataforma cruzada Common Language Infrastructure (CLI) no .NET , mas também pode gerar JavaScript e código de unidade de processamento gráfico (GPU).

F # é desenvolvido pela F # Software Foundation , Microsoft e colaboradores abertos. Um compilador de plataforma cruzada de código aberto para F # está disponível na F # Software Foundation. F # é uma linguagem com suporte total no Visual Studio e JetBrains Rider . Plug-ins que suportam F # existem para muitos editores amplamente usados, mais notavelmente a extensão Ionide para Visual Studio Code e integrações para outros editores, como Vim e Emacs .

F # é um membro da família de linguagens ML e se originou como uma implementação do .NET Framework de um núcleo da linguagem de programação OCaml . Também foi influenciado por C # , Python , Haskell , Scala e Erlang .

História

Versões

No decorrer de seu desenvolvimento, a linguagem passou por várias versões:

Versão Especificação de linguagem Encontro Plataformas Tempo de execução
F # 1.x Maio de 2005 janelas .NET 1.0 - 3.5
F # 2.0 Agosto de 2010 Abril de 2010 Linux , macOS , Windows .NET 2.0 - 4.0, Mono
F # 3.0 Novembro de 2012 Agosto de 2012 Linux , macOS , Windows ;
JavaScript , GPU
.NET 2.0 - 4.5, Mono
F # 3.1 novembro de 2013 outubro 2013 Linux , macOS , Windows ;
JavaScript , GPU
.NET 2.0 - 4.5, Mono
F # 4.0 Janeiro de 2016 Julho de 2015
F # 4.1 Maio de 2018 Março de 2017 Linux , macOS , Windows ,

JavaScript , GPU

.NET 3.5 - 4.6.2, .NET Core , Mono
F # 4.5 Agosto de 2018 Linux , macOS , Windows ,

JavaScript , GPU

.NET 4.5 - 4.7.2, .NET Core SDK 2.1.400
F # 4.6 Março de 2019 Linux , macOS , Windows ,

JavaScript , GPU

.NET 4.5 - 4.7.2, .NET Core SDK 2.2.300
F # 4.7 Setembro de 2019 Linux , macOS , Windows ,

JavaScript , GPU

.NET 4.5 - 4.8, .NET Core SDK 3.0.100
F # 5.0 Novembro de 2020 Linux , macOS , Windows ,

JavaScript , GPU

.NET SDK 5.0.100

Evolução da linguagem

F # usa um processo aberto de desenvolvimento e engenharia. O processo de evolução da linguagem é gerenciado por Don Syme da Microsoft Research como o ditador benevolente para a vida (BDFL) para o design da linguagem, juntamente com a F # Software Foundation. As versões anteriores da linguagem F # foram projetadas pela Microsoft e pela Microsoft Research usando um processo de desenvolvimento fechado.

F # é originário da Microsoft Research , Cambridge, Reino Unido. A linguagem foi originalmente desenhada e implementada por Don Syme , de acordo com quem na equipe fsharp, eles dizem que o F é para "Diversão". Andrew Kennedy contribuiu para o design de unidades de medida . As Ferramentas Visual F # para Visual Studio são desenvolvidas pela Microsoft. A F # Software Foundation desenvolveu o compilador e as ferramentas de código aberto F #, incorporando a implementação do compilador de código aberto fornecida pela equipe do Microsoft Visual F # Tools.

Resumo das versões
Recursos adicionados
F # 1.0
  • Programação funcional
  • Sindicatos discriminados
  • Registros
  • Tuplas
  • Correspondência de padrões
  • Abreviações de tipo
  • Programação orientada a objetos
  • Structs
  • Arquivos de assinatura
  • Arquivos de script
  • Programação imperativa
  • Módulos (sem functores)
  • Módulos aninhados
  • Interoperabilidade .NET
F # 2.0
  • Padrões ativos
  • Unidades de medida
  • Expressões de sequência
  • Programação assíncrona
  • Programação de agente
  • Membros de extensão
  • Argumentos nomeados
  • Argumentos opcionais
  • Fatiamento de matriz
  • Citações
  • Interoperabilidade nativa
  • Expressões de computação
F # 3.0
  • Provedores de tipo
  • Expressões de consulta LINQ
  • Atributo CLIMutable
  • Strings entre aspas triplas
  • Auto-propriedades
  • Unidades de medida fornecidas
F # 3.1
  • Campos de tipo de união nomeados
  • Extensões para corte de matriz
  • Aprimoramentos de inferência de tipo
F # 4.0
  • Printf em valores unificados
  • Inicializadores de propriedade de extensão
  • Tipos fornecidos não nulos
  • Construtores primários como funções
  • Parâmetros estáticos para métodos fornecidos
  • Interpolação Printf
  • Gramática #if estendida
  • Atributo Tailcall
  • Múltiplas instanciações de interface
  • Args de tipo opcional
  • Dicionários Params
F # 4.1
  • Tuplas de estrutura que inter-operam com tuplas C #
  • Anotações de estrutura para registros
  • Anotações de estrutura para uniões discriminadas de caso único
  • Sublinhados em literais numéricos
  • Atributos do argumento da informação do chamador
  • Tipo de resultado e algumas funções básicas de resultado
  • Tipos e módulos mutuamente referenciais dentro do mesmo arquivo
  • Sintaxe "Módulo" implícita em módulos com nome compartilhado como tipo
  • Retorna Byref, suportando o consumo de métodos de retorno de ref C #
  • Melhorias na mensagem de erro
  • Suporte para 'fixo'
F # 4.5
  • Alinhamento de versão de binário, pacote e linguagem
  • Suporte para 'Span <T>' e tipos relacionados
  • Capacidade de produzir retornos 'byref'
  • O tipo 'voidptr'
  • Os tipos 'inref <' T> 'e' outref <'T>' para representar somente leitura e somente gravação 'byref's
  • Estruturas 'IsByRefLike'
  • Estruturas 'IsReadOnly'
  • Suporte ao método de extensão para 'byref <' T> '/' inref <'T>' / 'outref <' T> '
  • 'partida!' palavra-chave em expressões de computação
  • Upcast relaxado com 'rendimento' em expressões F # seq / lista / array
  • Recuo relaxado com expressões de lista e matriz
  • Casos de enumeração emitidos como públicos
F # 4.7
  • Rendimentos implícitos
  • Não é mais necessário sublinhado duplo
  • Relaxamentos de indentação para parâmetros passados ​​para construtores e métodos estáticos
  • função 'nameof'
  • Abrir classes estáticas
F # 5.0
  • FSharp.Core agora visa apenas netstandard2.0
  • Referências de pacote em scripts F #
  • Suporte para notebooks Jupyter, nteract e VSCode
  • Interpolação de String
  • Suporte para nameof
  • Declarações de tipo aberto
  • Fatias aprimoradas
  • Melhorias nas cotações F #
  • Expressões de computação aplicada
  • Rastreamentos de pilha aprimorados em F # assíncrono e outras expressões de computação
  • Interop. .NET aprimorada
  • Melhor desempenho de mapa e conjunto em FSharp.Core
  • Melhor desempenho do compilador
  • Análise de compilador aprimorada para autores de biblioteca

Visão geral da linguagem

Programação funcional

F # é uma linguagem de programação funcional. Isso significa que em F # as funções são enfatizadas mais do que objetos e estruturas e outras construções de programação tradicionais. F # é uma linguagem funcional de tipagem forte que usa inferência de tipo . F # também permite anotações de tipo explícitas e as requer em algumas situações.

F # é uma linguagem baseada em expressão que usa avaliação rápida e também, em alguns casos, avaliação preguiçosa . Cada instrução em F #, incluindo ifexpressões, tryexpressões e loops, é uma expressão combinável com um tipo estático. Funções e expressões que não retornam nenhum valor têm um tipo de retorno de unit. F # usa a letpalavra - chave para vincular valores a um nome. Por exemplo:

let x = 3 + 4

vincula o valor 7ao nome x.

Novos tipos são definidos usando a typepalavra - chave. Para programação funcional, F # fornece tupla , registro , união discriminada , lista , opção e tipos de resultado . Uma tupla representa um conjunto de n valores, onde n ≥ 0. O valor n é chamado de aridade da tupla. Uma tupla de 3 seria representada como (A, B, C), onde A, B e C são valores de tipos possivelmente diferentes. Uma tupla pode ser usada para armazenar valores apenas quando o número de valores é conhecido em tempo de design e permanece constante durante a execução.

Um registro é um tipo onde os membros de dados são nomeados. Aqui está um exemplo de definição de registro:

 type R = 
        { Name : string 
         Age : int }

Os registros podem ser criados como . A palavra-chave é usada para criar uma cópia de um registro, como em , que cria um novo registro copiando e alterando o valor do campo (assumindo que o registro criado no último exemplo foi nomeado ). let r = { Name="AB"; Age=42 }with{ r with Name="CD" }rNamer

Uma união discriminada tipo é um tipo seguro versão do sindicatos C . Por exemplo,

 type A = 
    | UnionCaseX of string
    | UnionCaseY of int

Os valores do tipo de união podem corresponder a qualquer caso de união. Os tipos de valores transportados por cada caso de união estão incluídos na definição de cada caso.

O tipo de lista é uma lista vinculada imutável representada por uma notação ( é o operador contras ) ou uma abreviatura como . Uma lista vazia é escrita . O tipo de opção é um tipo de união discriminado com opções ou . Os tipos F # podem ser genéricos , implementados como tipos .NET genéricos. head::tail::[item1; item2; item3][]Some(x)None

F # oferece suporte a funções lambda e encerramentos . Todas as funções em F # são valores de primeira classe e são imutáveis. As funções podem ser curry . Sendo valores de primeira classe, as funções podem ser passadas como argumentos para outras funções. Como outras linguagens de programação funcional, F # permite a composição de funções (ciência da computação) usando os operadores >>e <<.

F # fornece expressões de sequência que definem uma sequênciaseq { ... }, lista[ ... ]ou array[| ... |]por meio de código que gera valores. Por exemplo,

 seq { for b in 0 .. 25 do
           if b < 15 then
               yield b*b }

forma uma sequência de quadrados de números de 0 a 14, filtrando os números do intervalo de números de 0 a 25. As sequências são geradores - os valores são gerados sob demanda (ou seja, são avaliados lentamente ) - enquanto as listas e matrizes são avaliadas avidamente .

F # usa correspondência de padrões para vincular valores a nomes. A correspondência de padrões também é usada ao acessar uniões discriminadas - a união é o valor correspondido com as regras de padrão e uma regra é selecionada quando uma correspondência é bem-sucedida. F # também oferece suporte a padrões ativos como uma forma de correspondência de padrões extensível. É usado, por exemplo, quando existem várias maneiras de correspondência em um tipo.

F # suporta uma sintaxe geral para definir cálculos composicionais chamados expressões de computação . Expressões de sequência, cálculos assíncronos e consultas são tipos particulares de expressões de computação. Expressões de computação são uma implementação dopadrãomonad.

Programação imperativa

O suporte F # para programação imperativa inclui

Valores e campos de registro também podem ser rotulados como mutable. Por exemplo:

// Define 'x' with initial value '1'
let mutable x = 1
// Change the value of 'x' to '3'
x <- 3

Além disso, o F # oferece suporte ao acesso a todos os tipos e objetos CLI, como aqueles definidos no System.Collections.Genericnamespace que define estruturas de dados imperativas.

Programação orientada a objetos

Como outras linguagens CLI ( Common Language Infrastructure ), o F # pode usar tipos CLI por meio da programação orientada a objetos. O suporte F # para programação orientada a objetos em expressões inclui:

  • Notação de ponto, por exemplo, x.Name
  • Expressões de objeto, por exemplo, { new obj() with member x.ToString() = "hello" }
  • Construção de objetos, por exemplo, new Form()
  • Testes de tipo, por exemplo, x :? string
  • Coações de tipo, por exemplo, x :?> string
  • Argumentos nomeados, por exemplo, x.Method(someArgument=1)
  • Setters nomeados, por exemplo, new Form(Text="Hello")
  • Argumentos opcionais, por exemplo, x.Method(OptionalArgument=1)

O suporte para programação orientada a objetos em padrões inclui

  • Testes de tipo, por exemplo, :? string as s
  • Padrões ativos, que podem ser definidos sobre os tipos de objeto

As definições de tipo de objeto F # podem ser definições de tipo de classe, estrutura, interface, enum ou delegado, correspondendo aos formulários de definição encontrados em C # . Por exemplo, aqui está uma classe com um construtor tomando um nome e idade e declarando duas propriedades.

/// A simple object type definition
type Person(name : string, age : int) =
    member x.Name = name
    member x.Age = age

Programação assíncrona

F # oferece suporte à programação assíncrona por meio de fluxos de trabalho assíncronos . Um fluxo de trabalho assíncrono é definido como uma sequência de comandos dentro de um async{ ... }, como em

let asynctask = 
    async { let req = WebRequest.Create(url)
            let! response = req.GetResponseAsync()
            use stream = response.GetResponseStream()
            use streamreader = new System.IO.StreamReader(stream)
            return streamreader.ReadToEnd() }

O let!indica que a expressão à direita (obtendo a resposta) deve ser feita de forma assíncrona, mas o fluxo só deve continuar quando o resultado estiver disponível. Em outras palavras, do ponto de vista do bloco de código, é como se obter a resposta fosse uma chamada de bloqueio, enquanto do ponto de vista do sistema, a thread não será bloqueada e poderá ser utilizada para processar outros fluxos enquanto o resultado necessário para este não se torna disponível.

O bloco assíncrono pode ser chamado usando a Async.RunSynchronouslyfunção. Vários blocos assíncronos podem ser executados em paralelo usando a Async.Parallelfunção que pega uma lista de asyncobjetos (no exemplo, asynctaské um objeto assíncrono) e cria outro objeto assíncrono para executar as tarefas nas listas em paralelo. O objeto resultante é invocado usando Async.RunSynchronously. A inversão de controle em F # segue esse padrão.

Programação paralela

Programação paralela é suportado, em parte, através do Async.Parallel, Async.Starte outras operações que são executados blocos assíncronas em paralelo.

A programação paralela também é suportada por meio de Array.Paralleloperadores de programação funcional na biblioteca padrão F #, uso direto do System.Threading.Tasksmodelo de programação de tarefas, uso direto de pool de threads .NET e threads .NET e por meio da tradução dinâmica de código F # para mecanismos de execução paralela alternativos, como Código GPU .

Unidades de medida

O sistema do tipo F # oferece suporte à verificação de unidades de medida para números. O recurso de unidades de medida se integra com a inferência de tipo F # para exigir anotações de tipo mínimas no código do usuário.

Metaprogramação

F # permite algumas formas de personalização de sintaxe por meio de metaprogramação para oferecer suporte à incorporação de linguagens específicas de domínio personalizadas na linguagem F #, particularmente por meio de expressões de computação.

F # inclui um recurso para metaprogramação em tempo de execução chamado cotações. Uma expressão de aspas é avaliada como uma representação de árvore de sintaxe abstrata das expressões F #. Da mesma forma, as definições marcadas com o [<ReflectedDefinition>]atributo também podem ser acessadas em seu formulário de cotação. As citações F # são usadas para vários fins, incluindo compilar o código F # em código JavaScript e GPU . (As cotações representam suas expressões de código F # como dados para uso por outras partes do programa, ao mesmo tempo em que exigem que o código F # seja sintaticamente correto).

Programação rica em informações

O F # 3.0 introduziu uma forma de metaprogramação em tempo de compilação por meio da geração de tipo estaticamente extensível, chamada de provedores de tipo F #. Os provedores de tipo F # permitem que o compilador F # e as ferramentas sejam estendidos com componentes que fornecem informações de tipo para o compilador sob demanda em tempo de compilação. Os provedores do tipo F # têm sido usados ​​para fornecer acesso fortemente tipado a fontes de informação conectadas de uma forma escalonável, incluindo o gráfico de conhecimento do Freebase .

No F # 3.0, os recursos de cotação e expressão de cálculo do F # são combinados para implementar consultas LINQ . Por exemplo:

// Use the OData type provider to create types that can be used to access the Northwind database.
open Microsoft.FSharp.Data.TypeProviders

type Northwind = ODataService<"http://services.odata.org/Northwind/Northwind.svc">
let db = Northwind.GetDataContext()

// A query expression.
let query1 = query { for customer in db.Customers do
                     select customer }

A combinação de provedores de tipo, consultas e programação funcional fortemente tipada é conhecida como programação rica em informações .

Programação de agente

F # oferece suporte a uma variação do modelo de programação de Ator por meio da implementação na memória de agentes assíncronos leves. Por exemplo, o código a seguir define um agente e posta 2 mensagens:

let counter =
    MailboxProcessor.Start(fun inbox ->
        let rec loop n =
            async { do printfn "n = %d, waiting..." n
                    let! msg = inbox.Receive()
                    return! loop(n+msg) }
        loop 0)

Ferramentas de desenvolvimento

  • O Visual Studio , com as ferramentas Visual F # da Microsoft instaladas, pode ser usado para criar, executar e depurar projetos F #. As ferramentas do Visual F # incluem um console interativo de loop de leitura / avaliação (REPL) hospedado no Visual Studio que pode executar o código F # conforme ele é escrito. O Visual Studio para Mac também oferece suporte total a projetos F #.
  • O código do Visual Studio contém suporte total para F # por meio da extensão Ionide .
  • F # pode ser desenvolvido com qualquer editor de texto. Existe suporte específico em editores como o Emacs .
  • JetBrains Rider é otimizado para o desenvolvimento do código F # a partir da versão 2019.1.
  • LINQPad tem suporte para F # desde a versão 2.x.

Áreas de aplicação

F # é uma linguagem de programação de propósito geral .

Programação da Web

A SAFE Stack é uma pilha F # ponta a ponta para desenvolver aplicativos da web. Ele usa ASP.NET Core no lado do servidor e Fable no lado do cliente.

Uma opção alternativa de F # ponta a ponta é a estrutura WebSharper .

Desenvolvimento de aplicativos multiplataforma

F # pode ser usado junto com as Ferramentas do Visual Studio para Xamarin para desenvolver aplicativos para iOS e Android . A biblioteca Fabulous oferece uma interface funcional mais confortável.

Programação analítica

Entre outros, F # é usado para programação financeira quantitativa, negociação de energia e otimização de portfólio, aprendizado de máquina, inteligência de negócios e jogos sociais no Facebook .

Na década de 2010, o F # foi posicionado como uma alternativa otimizada ao C # . A capacidade de script do F # e a compatibilidade entre idiomas com todos os produtos Microsoft o tornaram popular entre os desenvolvedores.

Scripting

F # pode ser usado como uma linguagem de script, principalmente para scripts de loop de leitura-avaliação de desktop (REPL).

Comunidade de código aberto

A comunidade de código aberto F # inclui a F # Software Foundation e o F # Open Source Group no GitHub . Os projetos F # de código aberto populares incluem:

  • Fable , um transpiler de F # para Javascript baseado em Babel .
  • Paket , um gerenciador de pacotes alternativo para .NET que ainda pode usar repositórios NuGet , mas possui gerenciamento de versão centralizado.
  • FAKE , um sistema de compilação amigável ao F #.
  • Giraffe , um middleware orientado funcionalmente para ASP.NET Core .
  • Suave , um servidor web leve e biblioteca de desenvolvimento web.

Compatibilidade

O F # apresenta um "modo de compatibilidade de ML" legado que pode compilar diretamente programas escritos em um grande subconjunto de OCaml, sem functores, objetos, variantes polimórficas ou outras adições.

Exemplos

Seguem algumas pequenas amostras:

// This is a comment for a sample hello world program.
printfn "Hello World!"

Uma classe Person com um construtor que recebe um nome, idade e duas propriedades imutáveis.

/// This is a documentation comment for a type definition.
type Person(name : string, age : int) =
    member x.Name = name
    member x.Age = age
    
/// class instantiation
let mrSmith = Person("Smith", 42)

Um exemplo simples que costuma ser usado para demonstrar a sintaxe de linguagens funcionais é a função fatorial para inteiros de 32 bits não negativos, mostrada aqui em F #:

/// Using pattern matching expression
let rec factorial n =
    match n with
    | 0 -> 1
    | _ -> n * factorial (n - 1)

/// For a single-argument functions there is syntactic sugar (pattern matching function):
let rec factorial = function 
    | 0 -> 1 
    | n -> n * factorial (n - 1)
    
/// Using fold and range operator
let factorial n = [1..n] |> Seq.fold (*) 1

Exemplos de iteração:

/// Iteration using a 'for' loop
let printList lst = 
    for x in lst do
        printfn "%d" x

/// Iteration using a higher-order function
let printList2 lst = 
    List.iter (printfn "%d") lst

/// Iteration using a recursive function and pattern matching
let rec printList3 lst =
    match lst with
    | [] -> ()
    | h :: t ->
        printfn "%d" h
        printList3 t

Exemplos de Fibonacci:

/// Fibonacci Number formula
let fib n =
    let rec g n f0 f1 =
        match n with
        | 0 -> f0
        | 1 -> f1
        | _ -> g (n - 1) f1 (f0 + f1)
    g n 0 1

/// Another approach - a lazy infinite sequence of Fibonacci numbers
let fibSeq = Seq.unfold (fun (a,b) -> Some(a+b, (b, a+b))) (0,1)

// Print even fibs
[1 .. 10]
|> List.map     fib
|> List.filter  (fun n -> (n % 2) = 0)
|> printList

// Same thing, using a list expression
[ for i in 1..10 do
    let r = fib i
    if r % 2 = 0 then yield r ]
|> printList

Um exemplo de programa Windows Forms:

// Open the Windows Forms library
open System.Windows.Forms

// Create a window and set a few properties
let form = new Form(Visible=true, TopMost=true, Text="Welcome to F#")

// Create a label to show some text in the form
let label =
    let x = 3 + (4 * 5)
    new Label(Text = sprintf "x = %d" x)

// Add the label to the form
form.Controls.Add(label)

// Finally, run the form
[<System.STAThread>]
Application.Run(form)

Amostra de programação paralela assíncrona (CPU paralela e tarefas de E / S):

/// A simple prime number detector
let isPrime (n:int) =
   let bound = int (sqrt (float n))
   seq {2 .. bound} |> Seq.forall (fun x -> n % x <> 0)

// We are using async workflows
let primeAsync n =
    async { return (n, isPrime n) }

/// Return primes between m and n using multiple threads
let primes m n =
    seq {m .. n}
        |> Seq.map primeAsync
        |> Async.Parallel
        |> Async.RunSynchronously
        |> Array.filter snd
        |> Array.map fst

// Run a test
primes 1000000 1002000
    |> Array.iter (printfn "%d")

Veja também

Notas

Referências

  • Syme, Don ; Granicz, Adam; Cisternino, Antonio (2007), Expert F # , Apress
  • Harrop, Jon (2010), Visual F # 2010 for Technical Computing , Flying Frog Consultancy
  • Pickering, Robert (2007), Foundations of F # , Apress
  • Smith, Chris (2009), Programming F # , O'Reilly
  • Petricek, Tomas (2009), Real World Functional Programming With Examples in F # e C # , Manning Publications
  • Hansen, Michael; Rischel, Hans (2013), Functional Programming Using F # , Cambridge University Press
  • Astborg, Johan (2013), F # for Quantitative Finance , Packt Publishing
  • Lundin, Mikael (2015), Testing with F # , Packt Publishing

links externos