Em que áreas o uso do F # pode ser mais apropriado que o C #? [fechadas]

210

Nos últimos anos, o F # evoluiu para um dos idiomas totalmente suportados da Microsoft, empregando muitas idéias incubadas em OCaml, ML e Haskell.

Nos últimos anos, o C # estendeu seus recursos de propósito geral, introduzindo cada vez mais recursos de linguagem funcional: LINQ (compreensão de lista), Lambdas, Encerramentos, Delegados Anônimos e mais ...

Dada a adoção pelo C # desses recursos funcionais e a taxonomia do F # como uma linguagem funcional impura (permite que você acesse as bibliotecas da estrutura ou mude o estado compartilhado quando uma função é chamada, se você quiser), há uma forte semelhança entre os dois idiomas, embora cada um tenha seu própria ênfase primária oposta polar.

Estou interessado em qualquer modelo de sucesso que empregue esses dois idiomas em seus programas poliglotas de produção e também nas áreas do software de produção (aplicativos da web, aplicativos clientes, aplicativos de servidor) que você escreveu em F # no ano passado, ou que você teria anteriormente escrito em c #.

Peter McG
fonte

Respostas:

258

Escrevi um pedido para equilibrar o cronograma nacional de geração de energia de um portfólio de usinas de energia para uma posição comercial de uma empresa de energia. Os componentes do cliente e do servidor estavam em C #, mas o mecanismo de cálculo foi escrito em F #.

O uso do F # para abordar a complexidade no coração deste aplicativo demonstra claramente um ponto ideal para a linguagem no software corporativo, ou seja, a análise algoritmicamente complexa de grandes conjuntos de dados. Minha experiência foi muito positiva. Em particular:

Unidades de medida A indústria em que trabalho está repleta de unidades. As equações que implementei (geralmente de natureza geométrica) tratavam de unidades de tempo, potência e energia. Fazer com que o sistema de tipos verifique a exatidão das unidades de entradas e saídas de funções economiza muito tempo, tanto em termos de teste quanto de leitura / compreensão do código. Ele erradica toda uma classe de erros aos quais os sistemas anteriores estavam propensos.

Programação exploratória O trabalho com arquivos de script e o REPL (F # Interactive) me permitiu explorar o espaço da solução com mais eficiência antes de me comprometer com uma implementação do que o loop de edição / compilação / execução / teste mais tradicional. É uma maneira muito natural de um programador desenvolver sua compreensão do problema e das tensões de design em jogo.

Teste de unidade O código escrito usando funções sem efeito colateral e estruturas de dados imutáveis ​​é uma alegria para testar. Não há interações complexas e dependentes do tempo para estragar tudo ou grandes conjuntos de dependências a serem ridicularizados.

Interoperação Eu defini a interface para o mecanismo de cálculo em C # e implementei o cálculo em F #. O mecanismo de cálculo poderia então ser injetado em qualquer módulo C # que precisasse usá-lo sem nenhuma preocupação com a interoperabilidade. Desatado. O programador de C # nunca precisa saber.

Redução de código Muitos dos dados alimentados no mecanismo de cálculo estavam na forma de vetores e matrizes. Funções de ordem superior as comem no café da manhã com barulho mínimo e código mínimo. Lindo.

Falta de bugs A programação funcional pode parecer estranha. Eu posso estar trabalhando em um algoritmo, tentando fazer com que o código passe no verificador de tipos, mas assim que o verificador de tipos estiver satisfeito, funciona. É quase binário, ou ele não compila ou está correto. Os erros estranhos de maiúsculas e minúsculas são minimizados, as funções de recursão e de ordem superior removem muitos códigos de contabilidade que introduzem erros de maiúsculas e minúsculas.

Paralelismo A pureza funcional da implementação resultante o torna adequado para explorar o paralelismo inerente no processamento de vetores de dados. Talvez seja aqui que eu irei a seguir agora que o .NET 4 foi lançado.

primos de simon
fonte
18
+1 para explicar por que o F # é muito adequado para mecanismos de processamento de números. Outro +1 (virtual) +1 para mencionar unidades de medida. Essa parte do idioma merece ser mencionada com mais frequência.
Cfern
5
Grande resposta, relevante, contemporânea e contornos F # adequação para lidar com a complexidade, eu aprendi muito de lê-lo, graças
Peter McG
Ótima resposta Simon, e como Don mencionou ontem à noite, citado em seus slides recentes. Hora de adicionar um link "adicionar ao carrinho"?
Chris Ballard
1
oi, você pode nos contar mais sobre a arquitetura de seus aplicativos?
Nikos
76

Durante meu estágio na Microsoft Research, trabalhei em algumas partes do Visual Studio IntelliSense for F # (que é escrito em F #). Eu já tinha alguma experiência com o IntelliSense de projetos anteriores em C #, então acho que posso comparar os dois.

  • A extensibilidade do Visual Studio ainda é baseada no COM, portanto, você precisa lidar com objetos .NET não muito agradáveis ​​(e definitivamente não funcionais), mas não acho que exista grande diferença entre C # e F # (funciona sem problemas) de F #)

  • As estruturas de dados usadas para representar o código do programa em F # são principalmente uniões discriminadas (que não são suportadas em C # de maneira razoável) e isso faz uma enorme diferença para esse tipo de aplicativo (onde você precisa processar estruturas em árvore, como código de programa ) Uniões discriminadas e correspondência de padrões permitem estruturar melhor o código (mantenha a funcionalidade relacionada em um só lugar, em vez de tê-lo em todo lugar em métodos virtuais)

Anteriormente, também trabalhei no provedor CodeDOM para F # (também escrito em F #). Na verdade, fiz as primeiras experiências em C #, mas depois converti o código em F #.

  • O provedor CodeDOM precisa percorrer alguma estrutura representada usando objetos .NET, portanto, não há muito espaço para inventar suas próprias representações de dados (que é a área em que o F # pode oferecer bons benefícios).

  • No entanto, havia muitos recursos pequenos de F # que tornaram a tarefa mais fácil. Como você precisa produzir uma string, defini operadores personalizados para criar strings (usando StringBuilder) e implementei o código usando-os e funções de ordem superior (por exemplo, para formatar a lista de objetos separados usando a string especificada etc.), o que removeu muitos repetição (e foreachloops tediosos ).

Estes são dois exemplos relativamente específicos, mas ambos estão relacionados ao trabalho com representações de programas, expressões ou, mais geralmente, estruturas complexas de dados semelhantes a árvores. Eu acho que nessa área, F # é definitivamente uma boa escolha (independentemente dos recursos funcionais em C #).

Tomas Petricek
fonte
6
Muito interessante, mais evidências de que a aceitação de F # na Microsoft é certamente alta, que ótimo estágio que deve ter sido!
Peter McG
43

Enviamos o primeiro produto comercial do mundo escrito em F # ( F # para visualização ) e o segundo ( F # para Numerics ), bem como a primeira literatura comercial sobre F # ( The F # .NET Journal ) e escrevemos e publicamos o único livro sobre a versão atual de F # ( Visual F # 2010 para computação técnica ).

Estávamos enviando produtos de acordo com linhas semelhantes escritas em C # (por exemplo, isto ), mas também tínhamos uma sólida experiência no uso comercial do OCaml. Éramos os primeiros adeptos entusiasmados do F # quando ainda era um protótipo de pesquisa em 2006 porque reconhecemos o potencial de ter uma linguagem decente do tipo OCaml moderna na plataforma .NET de força industrial e, consequentemente, pressionamos para que ele fosse produzido. O resultado foi um sucesso incrível e o F # excedeu em muito nossas elevadas expectativas.

Para nós, o F # tem muitas vantagens diferentes e o usamos para uma ampla variedade de aplicações. Temos centenas de milhares de linhas de código F # em produção. Agora usamos F # para todos os nossos aplicativos LOB: nossas transações com cartão de crédito são processadas usando o código F #, nossas notificações de produtos são enviadas usando o código F #, nossas assinaturas são tratadas com o código F #, nossas contas são feitas com o código F # e assim por diante. Talvez o principal recurso do idioma que pague dividendos aqui seja a correspondência de padrões. Até usamos F # para colorir a sintaxe e destacar nosso último livro ...

Nossa biblioteca de visualização é uma grande vendedora e suas funcionalidades estão centradas na execução interativa de F # no Visual Studio. Nossa biblioteca aumenta isso com a capacidade de gerar visualizações interativas em 2D e 3D com o mínimo de esforço (por exemplo, apenasPlot([Function sin], (-6., 6.))traçar uma onda senoidal). Em particular, todos os problemas de encadeamento são completamente automatizados, para que os usuários não precisem se preocupar com threads e despacho da interface do usuário. Funções de primeira classe e preguiça foram extremamente valiosas ao escrever essa parte da biblioteca e os tipos de dados algébricos foram usados ​​extensivamente em outros lugares. O desempenho previsível também se mostrou valioso aqui quando nossos clientes encontraram bugs de desempenho nos testes de impacto do WPF e conseguiram reimplementar facilmente o código relevante no F # para uma melhoria de 10.000 × no desempenho. Devido à natureza de forma livre da GUI deste produto, o designer da GUI e o C # não seriam benéficos.

Grande parte do nosso trabalho gira em torno de métodos numéricos, incluindo nossas bibliotecas comerciais e livros. O F # é muito mais forte nessa área do que o C # porque oferece abstrações de alto nível (por exemplo, funções de ordem superior) com penalidades mínimas de desempenho. Nosso resultado mais convincente nesse contexto foi a criação de uma implementação simples, mas generalizada, da decomposição QR da álgebra linear 20 vezes menor que o código Fortran da implementação de referência do LAPACK, até 3 vezes mais rápida que a Intel Math ajustada pelo fornecedor Biblioteca de Kernel e mais genérica, porque nosso código pode lidar com matrizes de qualquer tipo, mesmo matrizes simbólicas!

No momento, estamos desenvolvendo componentes WPF / Silverlight em uma combinação de F # (para o interior) e C # (para o calço), criando aplicativos WPF para atuar como manuais interativos para nossos produtos de software e estou escrevendo um novo livro, Multicore F #, que será o guia definitivo para a programação paralela de memória compartilhada no .NET.

Jon Harrop
fonte
Você é o mesmo Jon Harrop que escreveu "F # for Scientists"?
Andre Artus
7
Sim. Eu escrevi F # para Scientists há 5 anos.
precisa
Você tem uma referência de algum tipo para o código de decomposição QR em F # mencionado em seu penúltimo parágrafo? Obrigado.
Samik R
@ SamikR: Não, desculpe. Esse é o código comercial. Foi fácil escrever, no entanto.
91311 Jon Harrop
@Jon qualquer palavra sobre Multicore F #?
precisa saber é o seguinte
25

Nos últimos 6 meses, trabalhei em uma camada de emulação do Vim para o Visual Studio 2010. É um produto gratuito com toda a fonte disponível gratuitamente no github

O projeto é dividido em 3 DLLs, representando uma camada distinta. Cada camada tem uma dll de teste de unidade correspondente.

  1. Motor Vim: F #
  2. Camada WPF para adornos e integração de editor: C #
  3. Camada de integração do Visual Studio: C #

Este é o primeiro grande projeto que eu já fiz com o F # e devo dizer que amo a linguagem. De várias maneiras, usei esse projeto como um método de aprendizado de F # (e essa curva de aprendizado é muito evidente se você examinar o histórico do projeto).

O que eu acho mais surpreendente no F # é o quão conciso é um idioma. O mecanismo Vim compreende a maior parte da lógica, mas apenas 30% da base geral de códigos.

JaredPar
fonte
19
Editor ... linguagem funcional ... vi emulação ... você reinventou o emacs. NOOOOOOOOOOOOOOOOOOOOOOO!
Ben Voigt
2
Exceto que é "100% certificada parênteses-livres" :)
Pavel Minaev
@Pavel, com exceção de tuplas é claro, e chamadas de método .net
JaredPar
26
Duas coisas de nota aqui. Primeiro, as tuplas não precisam ()no F # - o ,operador é o que as cria, assim let x = 1,2como uma tupla válida já sem parênteses. Segundo, qualquer par parens em F # pode ser substituído por pares de begin.. end(isso é herdado do ML) - portanto, por exemplo, "foo".IndexOf begin 'a', 1 endé uma chamada de método .NET válida. Então, se você sempre quis ser parens-livres, F # é uma linguagem que permite que você faça exatamente isso :)
Pavel Minaev
Comentário engraçado Pavel! Não sabia disso. Eu acho que em alguns casos com grandes blocos de agrupamento, eu poderia realmente preferem begin.. end. TAMBÉM: REGRAS VsVim!
Dan Fitch
13

Muitos testes de unidade para os componentes do F # Visual Studio estão escritos em F #. Eles são executados fora do VS, zombando dos vários bits do Visual Studio. A capacidade de consultar objetos anônimos que implementam interfaces é útil no lugar de uma estrutura / ferramenta de simulação. Eu posso escrever

let owpe : string list ref = ref []
let vsOutputWindowPane = 
    { new IVsOutputWindowPane with
        member this.Activate () = err(__LINE__)
        member this.Clear () = owpe := []; 0
        member this.FlushToTaskList () = VSConstants.S_OK
        member this.GetName(pbstrPaneName) = err(__LINE__)
        member this.Hide () = err(__LINE__)
        member this.OutputString(pszOutputString) = owpe := pszOutputString :: !owpe ; 0
        member this.OutputStringThreadSafe(pszOutputString) = owpe := pszOutputString :: !owpe ; 0
        member this.OutputTaskItemString(pszOutputString, nPriority, nCategory, pszSubcategory, nBitmap, pszFilename, nLineNum, pszTaskItemText) = err(__LINE__)
        member this.OutputTaskItemStringEx(pszOutputString, nPriority, nCategory, pszSubcategory, nBitmap, pszFilename, nLineNum, pszTaskItemText, pszLookupKwd) = err(__LINE__)
        member this.SetName(pszPaneName) = err(__LINE__)
    }            
DoSomethingThatNeedsA(vsOutputWindowPane)
assert( !owpe = expectedOutputStringList )

quando eu precisar de uma instância de, por exemplo, uma IVsOutputWindowPanepara passar para algum outro componente que eventualmente chamará OutputStringe Clear, em seguida, inspecionar o string list refobjeto no final do teste para ver se a saída esperada foi gravada.

Brian
fonte
Mais evidências interessantes de que a aceitação do F # na Microsoft é certamente alta. Eu não sabia que você poderia criar objetos anônimos que implementam as interfaces em F #
Peter McG
9

Criamos uma linguagem de mecanismo de regras customizada usando a implementação Lex-Yacc em F #

EDITAR para incluir resposta ao comentário

Não houve implementação de lex / yacc em C #. (tanto quanto sabíamos, e o F # one era)

Teria sido possível, mas uma dor absoluta para construir a análise nós mesmos.

Este tópico mostra algumas outras sugestões, como bibliotecas externas, mas nosso arquiteto principal é um veterano em linguagens funcionais; portanto, a opção de usar o F # foi um acéfalo.

johnc
fonte
+1 Você escreveria isso anteriormente em C #, era inadequado ou mais lento por um determinado motivo?
Peter McG
@ Peter McGrattan Pelo menos no momento da redação (o software), não havia implementação de lex / yacc em C #. Teria sido possível, mas uma dor absoluta para construir a análise nós mesmos. stackoverflow.com/questions/540593/lex-yacc-for-c mostra algumas outras sugestões, mas o nosso arquiteto líder é um veterano em linguagens funcionais, por isso a escolha de usar F # foi um acéfalo
johnc
Se você pensou que não havia lex / yacc para C #, estou com medo de que você simplesmente não tenha se esforçado o suficiente (existe um mais antigo que F #) que disse que se você precisa de lex / yacc F # é, na minha opinião, muito mais adequado martelo para que prego que c #
Rune FS
Eu mesmo usei o F # com fslex / fxyacc, embora não em um projeto de "produção" (ainda não lançado, de qualquer maneira) - destaque de sintaxe MSIL e extensão de conclusão de código para o VS. O principal benefício do uso de F # é que você obtém ADTs, que são muito convenientes para representar árvores de análise. Além disso, o uso de zíperes ( en.wikipedia.org/wiki/Zipper_(data_structure) ) facilita a execução de lexing incremental - e os zíperes, sendo funcionais, são mais fáceis de manipular de forma concisa no F #.
Pavel Minaev
7

Atualmente, estou trabalhando em uma compilação para uma linguagem de programação. O compilador é escrito inteiramente em F #. O compilador (além da compilação lex e analisador com lex / yacc) é basicamente compilado como muitas transformações de uma árvore complexa, como estrutura.

Conforme observado por outros, discriminam uniões e a correspondência de padrões facilita muito mais o trabalho com esse tipo de estrutura de dados do que despejar o código em métodos virtuais "em todo o lugar"

Eu não havia feito nenhum trabalho de F # antes de começar a trabalhar no compilador (no entanto, eu tinha compiladores buld em outra variante do OCaml chamada MoscowML) e, como Jared afirma, é visível no código que partes eu fiz primeiro, mas em geral achei o F # fácil para aprender a entrar novamente na mentalidade do FP depois de codificar principalmente OO por uma década, ainda demorará um pouco mais.

trabalhando com árvores à parte, acho que a capacidade de escrever código declarativo é o principal benefício do FP (incluído o F #) com código que descreve o algoritmo. Estou tentando implementar em contraste com o C # que descreve como implementei o algoritmo é uma grande vantagem.

Rune FS
fonte
6

Não é uma experiência pessoal, mas você pode ouvir um episódio de DNR (acho que é esse aqui ) em que eles conversam com o pessoal da Microsoft sobre F #. Eles escreveram a maior parte do sistema de pontuação do Xbox Live, que estava longe de ser trivial, usando F #. O sistema escalou massivamente centenas de máquinas e eles ficaram muito satisfeitos com ele.

Igor Zevaka
fonte
5

Não sei se está em produção, mas a IA de "The Path of Go" foi escrita em F #:

http://research.microsoft.com/en-us/events/techvista2010/demolist.aspx#ThePathofGo

The Path of Go: um jogo de pesquisa da Microsoft para Xbox 360

Esta demonstração mostra um jogo do Xbox 360, baseado no jogo Go, produzido internamente na Microsoft Research Cambridge. Go é um dos jogos de tabuleiro mais famosos do Leste Asiático, originário da China há 4000 anos. Por trás da simplicidade enganosa do jogo esconde grande complexidade. Leva apenas alguns minutos para aprender, mas leva uma vida inteira para dominar. Embora os computadores tenham superado as habilidades humanas no Chess, a implementação de uma IA competitiva para Go continua sendo um desafio de pesquisa. O jogo é alimentado por três tecnologias desenvolvidas na Microsoft Research Cambridge: uma IA capaz de jogar Go, a linguagem F # e TrueSkill ™ para combinar com jogadores online. A IA é implementada em F # e atende ao desafio de executar com eficiência na estrutura compacta .net no Xbox 360. Este jogo coloca você em várias cenas em 3D visualmente impressionantes. Foi totalmente desenvolvido em código gerenciado usando o ambiente XNA.

(Alguém já mencionou "TrueSkill".)

Brian
fonte
Fascinante: F # rodando na estrutura compacta do XBox. O FSharp.Core.dll junto com o FSharp.Core.optdata FSharp.Core.sigdata faz referência a assemblies não-CF?
Peter McG
1
O CTP é enviado com um FSharp.Core separado criado para o .NETCF. (Há também um FSharp.Core separado para Silverlight.)
Brian
O que é esse CTP de que você fala?
Jwosty