In quali settori l'uso di F # potrebbe essere più appropriato di C #? [chiuso]


210

Negli ultimi anni F # si è evoluto in uno dei linguaggi supportati da Microsoft impiegando molte idee incubate in OCaml, ML e Haskell.

Negli ultimi anni C # ha ampliato le sue funzionalità per scopi generali introducendo funzionalità linguistiche sempre più funzionali: LINQ (comprensione dell'elenco), Lambdas, Chiusure, Delegati anonimi e altro ...

Data l'adozione da parte di C # di queste caratteristiche funzionali e la tassonomia di F # come linguaggio funzionale impuro (ti consente di accedere alle librerie del framework o di cambiare lo stato condiviso quando viene chiamata una funzione se vuoi) c'è una forte somiglianza tra le due lingue anche se ognuna ha il suo enfasi primaria opposta polare.

Sono interessato a qualsiasi modello di successo che impieghi queste due lingue nei tuoi programmi di poliglotta di produzione e anche le aree all'interno del software di produzione (app Web, app client, app server) che hai scritto in F # nell'ultimo anno o così che avresti in precedenza scritto in C #.

Risposte:


258

Ho scritto una domanda per bilanciare il programma nazionale di generazione di energia per un portafoglio di centrali elettriche con una posizione commerciale per una compagnia energetica. I componenti client e server erano in C # ma il motore di calcolo era scritto in F #.

L'uso di F # per affrontare la complessità alla base di questa applicazione dimostra chiaramente un punto debole per il linguaggio all'interno del software aziendale, ovvero l'analisi algoritmicamente complessa di grandi set di dati. La mia esperienza è stata molto positiva. In particolare:

Unità di misura L'industria in cui lavoro è disseminata di unità. Le equazioni che ho implementato (spesso di natura geometrica) hanno trattato di unità di tempo, potere ed energia. Fare in modo che il sistema di tipi verifichi la correttezza delle unità degli ingressi e delle uscite delle funzioni fa risparmiare molto tempo, sia in termini di test che di lettura / comprensione del codice. Sradica un'intera classe di errori a cui erano soggetti i sistemi precedenti.

Programmazione esplorativa Lavorare con i file di script e REPL (F # Interactive) mi ha permesso di esplorare lo spazio della soluzione in modo più efficace prima di impegnarmi in un'implementazione rispetto al più tradizionale ciclo di modifica / compilazione / esecuzione / test. È un modo molto naturale per un programmatore di costruire la propria comprensione del problema e delle tensioni progettuali in gioco.

Test unitario Il codice scritto usando funzioni che non hanno effetti collaterali e strutture di dati immutabili è una gioia da testare. Non ci sono interazioni complesse dipendenti dal tempo per rovinare le cose o grandi insiemi di dipendenze da deridere.

Interoperabilità Ho definito l'interfaccia per il motore di calcolo in C # e implementato il calcolo in F #. Il motore di calcolo potrebbe quindi essere iniettato in qualsiasi modulo C # che necessitasse di utilizzarlo senza alcun problema di interoperabilità. Senza soluzione di continuità. Il programmatore C # non deve mai saperlo.

Riduzione del codice Gran parte dei dati immessi nel motore di calcolo era in forma di vettori e matrici. Le funzioni di ordine superiore le consumano a colazione con un minimo sforzo, un codice minimo. Bellissimo.

Mancanza di bug La programmazione funzionale può sembrare strana. Posso lavorare su un algoritmo, provando a fare in modo che il codice passi il controllo del tipo ma una volta che il controllo del tipo è soddisfatto, funziona. È quasi binario, non compilerà o sarà corretto. Gli errori dei casi con bordi strani sono ridotti al minimo, la ricorsione e le funzioni di ordine superiore rimuovono molto codice di contabilità che introduce errori nel caso con bordi.

Parallelismo La purezza funzionale dell'implementazione risultante la rende matura per lo sfruttamento del parallelismo intrinseco nell'elaborazione dei vettori di dati. Forse è qui che andrò dopo ora che .NET 4 è uscito.


18
+1 per spiegare perché F # è molto adatto per i motori di scricchiolio dei numeri. Un altro +1 (virtuale) per menzionare le unità di misura. Quella parte della lingua merita di essere menzionata più spesso.
cfern,

5
Ottima risposta, pertinente, contemporanea e delinea l'idoneità di F # per affrontare la complessità, ho imparato molto leggendolo, grazie
Peter McG

Ottima risposta Simone, e come ha ricordato Don ieri sera, citato nelle sue recenti diapositive. È ora di aggiungere un link "aggiungi al carrello"?
Chris Ballard,

1
ciao, puoi dirci di più sull'architettura delle tue app?
Nikos,

76

Durante il mio tirocinio presso Microsoft Research, ho lavorato su alcune parti di Visual Studio IntelliSense per F # (che è esso stesso scritto in F #). Ho già avuto qualche esperienza con IntelliSense da precedenti progetti C #, quindi penso di poter confrontare i due.

  • L'estensibilità di Visual Studio è ancora basata su COM, quindi è necessario occuparsi di oggetti che non sono oggetti .NET molto belli (e sicuramente non funzionali), ma non sento alcuna differenza sostanziale tra C # e F # (funziona senza problemi da F #)

  • Le strutture di dati utilizzate per rappresentare il codice del programma in F # sono per lo più sindacati discriminati (che non sono supportati in C # in alcun modo ragionevole) e questo fa una grande differenza per questo tipo di applicazione (dove è necessario elaborare strutture ad albero, come il codice del programma ). I sindacati discriminati e la corrispondenza dei modelli ti consentono di strutturare meglio il codice (mantieni la relativa funzionalità in un posto piuttosto che averlo ovunque nei metodi virtuali)

In precedenza, ho anche lavorato sul provider CodeDOM per F # (scritto anche in F #). In realtà ho fatto i primi esperimenti in C #, ma poi ho convertito il codice in F #.

  • Il provider CodeDOM deve attraversare alcune strutture rappresentate utilizzando oggetti .NET, quindi non c'è molto spazio per inventare le proprie rappresentazioni di dati (che è l'area in cui F # può offrire vantaggi interessanti).

  • Tuttavia, c'erano molte piccole funzionalità F # che rendevano il compito più semplice. Poiché è necessario produrre una stringa, ho definito operatori personalizzati per la creazione di stringhe (utilizzo StringBuilder) e implementato il codice utilizzandole e funzioni di ordine superiore (ad esempio per formattare l'elenco di oggetti separati utilizzando la stringa specificata, ecc.), Che ha rimosso molte ripetizione (e foreachloop noiosi ).

Questi sono due esempi relativamente specifici, ma entrambi sono collegati al lavoro con rappresentazioni di programmi o espressioni, o più in generale, strutture dati complesse simili ad alberi. Penso che in quest'area F # sia sicuramente una buona scelta (indipendentemente dalle caratteristiche funzionali di C #).


6
Molto interessante, ulteriori prove del fatto che l'adozione di F # all'interno di Microsoft è certamente elevata, che grande tirocinio che deve essere stato!
Peter McG,

43

Abbiamo spedito il primo prodotto commerciale al mondo scritto in F # ( F # per visualizzazione ) e il secondo ( F # per numerici ) nonché la prima letteratura commerciale su F # ( The F # .NET Journal ) e abbiamo scritto e pubblicato l'unico libro sulla versione corrente di F # ( Visual F # 2010 per il calcolo tecnico ).

Avevamo spedito prodotti seguendo linee simili scritte in C # (ad esempio, questo ) ma avevamo anche una solida base nell'uso commerciale di OCaml. Siamo stati entusiasti dei primi utenti di F # quando era ancora un prototipo di ricerca nel 2006 perché avevamo riconosciuto il potenziale di avere un linguaggio decente e moderno simile a OCaml sulla piattaforma .NET di livello industriale e, di conseguenza, abbiamo spinto per farlo produrre. Il risultato è stato un successo incredibile e F # ha superato di gran lunga le nostre aspettative elevate.

Per noi, F # ha molti vantaggi diversi e lo usiamo per un'ampia varietà di applicazioni. Abbiamo centinaia di migliaia di righe di codice F # in produzione. Ora utilizziamo F # per tutte le nostre app LOB: le nostre transazioni con carta di credito vengono elaborate utilizzando il codice F #, le notifiche dei nostri prodotti vengono inviate utilizzando il codice F #, le nostre sottoscrizioni vengono gestite utilizzando il codice F #, i nostri account vengono eseguiti utilizzando il codice F # e così via. Forse la caratteristica principale della lingua che paga i dividendi qui è il pattern matching. Abbiamo anche usato F # per evidenziare la sintassi del colore del nostro ultimo libro ...

La nostra libreria di visualizzazione è un grande venditore e le sue funzionalità sono incentrate sull'esecuzione interattiva F # in Visual Studio. La nostra biblioteca migliora questo con la capacità di generare visualizzazioni interattive 2D e 3D con il minimo sforzo (ad es. SoloPlot([Function sin], (-6., 6.))tracciare un'onda sinusoidale). In particolare, tutti i problemi di threading sono completamente automatizzati, quindi gli utenti non devono preoccuparsi dei thread e dell'invio dell'interfaccia utente. Le funzioni e la pigrizia di prima classe erano estremamente preziose quando si scriveva questa parte della biblioteca e i tipi di dati algebrici erano ampiamente utilizzati altrove. Anche le prestazioni prevedibili si sono rivelate preziose qui quando i nostri clienti hanno riscontrato errori di performance nei test di successo di WPF e sono stati facilmente in grado di reimplementare il codice pertinente in F # per un miglioramento delle prestazioni di 10.000 ×. A causa della natura in formato libero della GUI di questo prodotto, il designer della GUI e C # non sarebbero stati utili.

Gran parte del nostro lavoro ruota attorno a metodi numerici, comprese le nostre biblioteche commerciali e libri. F # è molto più forte in questo settore rispetto a C # perché offre astrazioni di alto livello (ad es. Funzioni di ordine superiore) con penalità di prestazione minime. Il nostro risultato più convincente in questo contesto è stata la creazione di un'implementazione semplice ma generalizzata della decomposizione QR dall'algebra lineare che era 20 volte più corta del codice Fortran dall'implementazione di riferimento di LAPACK, fino a 3 volte più veloce rispetto a Intel Math messa a punto dal fornitore Kernel Library e più generici perché il nostro codice è in grado di gestire matrici di qualsiasi tipo, anche matrici simboliche!

Attualmente stiamo sviluppando componenti WPF / Silverlight in un mix di F # (per l'intestino) e C # (per lo spessore), costruendo app WPF per fungere da manuali interattivi per i nostri prodotti software e sto scrivendo un nuovo libro, Multicore F #, che sarà la guida definitiva alla programmazione parallela a memoria condivisa su .NET.


Sei lo stesso Jon Harrop che ha scritto "F # for Scientists"?
Andre Artus,

7
Sì. Ho scritto F # per scienziati 5 anni fa.
Jon Harrop,

Hai una sorta di riferimento per il codice di decomposizione QR in F # che menzioni nel tuo penultimo paragrafo? Grazie.
Samik R,

@SamikR: No, scusa. Questo è un codice commerciale. Tuttavia, è stato facile scrivere.
Jon Harrop,

@Jon qualche parola su Multicore F #?
Professor Bigglesworth,

25

Negli ultimi 6 mesi circa, ho lavorato su un livello di emulazione Vim per Visual Studio 2010. È un prodotto gratuito con tutta la fonte disponibile gratuitamente su github

Il progetto è diviso in 3 DLL che rappresentano un livello distinto. Ogni strato ha una corrispondente unità test dll.

  1. Vim Engine: F #
  2. Livello WPF per ornamenti e integrazione dell'editor: C #
  3. Livello di integrazione di Visual Studio: C #

Questo è il primo grande progetto che abbia mai fatto con F # e devo dire che adoro la lingua. In molti modi ho usato questo progetto come metodo di apprendimento di F # (e questa curva di apprendimento è molto evidente se guardi attraverso la storia del progetto).

Quello che trovo più sorprendente di F # è quanto sia concisa una lingua. Il motore Vim comprende la maggior parte della logica ma comprende solo il 30% della base di codice complessiva.


19
Editor ... linguaggio funzionale ... vi emulazione ... hai reinventato emacs. NOOOOOOOOOOOOOOOOOOOOOOO!
Ben Voigt,

2
Solo che è "certificato senza parentesi al 100%" :)
Pavel Minaev

@Pavel, tranne che per le tuple ovviamente, e chiamate al metodo .net
JaredPar

26
Due cose degne di nota qui. Prima di tutto, le tuple non sono necessarie ()in F #: l' ,operatore è ciò che le crea, quindi let x = 1,2una tupla valida è già senza parentesi. In secondo luogo, qualsiasi coppia di parentesi in F # può essere sostituita da coppie di begin.. end(questo è ereditato da ML) - quindi, ad esempio, "foo".IndexOf begin 'a', 1 endè una chiamata al metodo .NET valida. Quindi, se hai mai voluto essere senza genitori, F # è una lingua che ti consente di fare proprio questo :)
Pavel Minaev,

Commento divertente Pavel! Non lo sapevo. Credo che, in alcuni casi con grandi blocchi di raggruppamento, potrei in realtà preferiscono begin.. end. ANCHE: REGOLE VsVim!
Dan Fitch,

13

Molti test unitari per i componenti di Visual Studio in F # sono scritti in F #. Corrono fuori da VS, deridendo i vari bit di Visual Studio. La capacità di creare oggetti anonimi che implementano interfacce è utile al posto di un framework / strumento beffardo. Posso solo scrivere

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 ho bisogno di un'istanza di esempio an IVsOutputWindowPaneper passare ad un altro componente che alla fine chiamerà OutputStringe Clear, quindi, ispeziono l' string list refoggetto alla fine del test per vedere se l'output previsto è stato scritto.


Interessante, più prove che l'assorbimento di F # all'interno di Microsoft è certamente elevato. Non sapevo che potresti creare oggetti anonimi che implementano interfacce in F #
Peter McG,

9

Abbiamo scritto un linguaggio del motore delle regole personalizzato utilizzando l'implementazione Lex-Yacc in F #

MODIFICA per includere la risposta ai commenti

Non è stata implementata lex / yacc in C #. (per quanto ne sapevamo, e l'F # uno era)

Sarebbe stato possibile, ma un vero dolore costruire noi stessi l'analisi.

Questo argomento mostra alcuni altri suggerimenti, come le librerie esterne, ma il nostro architetto capo è esperto nei linguaggi funzionali, quindi la scelta di usare F # è stata un gioco da ragazzi.


+1 Avresti scritto in precedenza in C # non era adatto o più lento per un certo motivo?
Peter McG,

@Peter McGrattan Almeno al momento della stesura (il software), non c'era l'implementazione di lex / yacc in C #. Sarebbe stato possibile, ma un vero dolore costruire noi stessi l'analisi. stackoverflow.com/questions/540593/lex-yacc-for-c mostra alcuni altri suggerimenti, ma il nostro architetto capo è
esperto

se pensavate che non ci fosse lex / yacc per C # temo che semplicemente non abbiate cercato abbastanza per farlo (ce n'è uno più vecchio di F #) che dicesse che se avete bisogno di lex / yacc F # è secondo me molto più adatto martello per quell'unghia di c #
Rune FS

Ho usato F # con fslex / fxyacc me stesso, anche se non in un progetto di "produzione" (non ancora rilasciato, comunque) - evidenziazione della sintassi MSIL ed estensione del completamento del codice per VS. Il principale vantaggio dell'utilizzo di F # è che si ottengono ADT, che sono molto convenienti per rappresentare alberi di analisi. Inoltre, l'uso delle cerniere ( en.wikipedia.org/wiki/Zipper_(data_structure) ) semplifica il lexing incrementale - e le cerniere, essendo funzionali, sono più facili da manipolare in modo conciso in F #.
Pavel Minaev,

7

Attualmente sto lavorando a una compilazione per un linguaggio di programmazione. Il compilatore è scritto interamente in F #. Il compilatore (a parte le build di lex e parser con lex / yacc) è fondamentalmente compilato come molta trasformazione di un albero complesso come la struttura.

Come notato da altri, discriminare i sindacati e la corrispondenza dei modelli rende molto più facile lavorare con questo tipo di struttura di dati rispetto al dumping del codice con metodi virtuali "ovunque"

Non avevo fatto alcun lavoro su F # prima di iniziare a lavorare sul compilatore (avevo comunque compilatori in un'altra variante OCaml chiamata MoscowML) e proprio come Jared afferma che dal codice sono visibili le parti che ho fatto prima ma in generale ho trovato F # facile per imparare ad entrare di nuovo nella mentalità del PQ dopo aver programmato principalmente OO per un decennio ci vorrà un po 'più di tempo.

lavorando a parte gli alberi, trovo che la capacità di scrivere codice dichiarativo sia il principale vantaggio di FP (incluso F #) con un codice che descrive l'algoritmo che sto cercando di implementare in contrasto con C # che descrive come ho implementato l'algortihm è un enorme vantaggio.


6

Non un'esperienza personale, ma puoi ascoltare un episodio di DNR (penso che sia questo ) in cui parlano alla gente di Microsoft di F #. Hanno scritto la maggior parte del sistema di punteggio di Xbox Live, che era tutt'altro che banale, usando F #. Il sistema si ridimensionò enormemente su centinaia di macchine e ne furono molto soddisfatti.


5

Non so se è in produzione, ma l'IA per "The Path of Go" è stata scritta in F #:

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

The Path of Go: un gioco di ricerca Microsoft per Xbox 360

Questa demo mostra un gioco Xbox 360, basato sul gioco Go, prodotto internamente alla Microsoft Research Cambridge. Go è uno dei giochi da tavolo più famosi dell'Asia orientale, nato in Cina 4000 anni fa. Dietro l'ingannevole semplicità del gioco si nasconde una grande complessità. Ci vogliono solo pochi minuti per imparare, ma ci vuole una vita per padroneggiare. Sebbene i computer abbiano superato le capacità umane di Chess, l'implementazione di un'intelligenza artificiale competitiva per Go rimane una sfida di ricerca. Il gioco è basato su tre tecnologie sviluppate presso Microsoft Research Cambridge: un'intelligenza artificiale in grado di giocare a Go, il linguaggio F # e TrueSkill ™ per abbinare i giocatori online. L'intelligenza artificiale è implementata in F # e risponde alla sfida di funzionare in modo efficiente nel framework compatto .net su Xbox 360. Questo gioco ti mette in una serie di scene 3D visivamente sbalorditive. È stato completamente sviluppato nel codice gestito usando l'ambiente XNA.

(Qualcun altro ha già menzionato "TrueSkill".)


Affascinante: F # in esecuzione sul framework compatto su XBox. FSharp.Core.dll insieme a FSharp.Core.optdata FSharp.Core.sigdata non fa riferimento a assembly non CF?
Peter McG,

1
Il CTP viene fornito con un FSharp.Core separato creato per .NETCF. (C'è anche un FSharp.Core separato per Silverlight.)
Brian,

Di cosa parla questo CTP?
Jwosty,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.