In welchen Bereichen könnte die Verwendung von F # geeigneter sein als C #? [geschlossen]

210

In den letzten Jahren hat sich F # zu einer der vollständig unterstützten Sprachen von Microsoft entwickelt, in der viele Ideen verwendet wurden, die in OCaml, ML und Haskell inkubiert wurden.

In den letzten Jahren hat C # seine Allzweckfunktionen um immer mehr funktionale Sprachfunktionen erweitert: LINQ (Listenverständnis), Lambdas, Closures, Anonyme Delegierte und mehr ...

Angesichts der Übernahme dieser Funktionsmerkmale durch C # und der Taxonomie von F # als unreine Funktionssprache (Sie können auf Framework-Bibliotheken zugreifen oder den gemeinsamen Status ändern, wenn eine Funktion aufgerufen wird, wenn Sie möchten) besteht eine starke Ähnlichkeit zwischen den beiden Sprachen, obwohl jede ihre eigene hat eigene polare entgegengesetzte Hauptbetonung.

Ich interessiere mich für erfolgreiche Modelle, die diese beiden Sprachen in Ihren Produktions-Polyglot-Programmen verwenden, sowie für die Bereiche innerhalb der Produktionssoftware (Web-Apps, Client-Apps, Server-Apps), die Sie im letzten Jahr oder so in F # geschrieben haben geschrieben in C #.

Peter McG
quelle

Antworten:

258

Ich habe einen Antrag geschrieben, um den nationalen Stromerzeugungsplan für ein Portfolio von Kraftwerken auf eine Handelsposition für ein Energieunternehmen abzustimmen. Die Client- und Serverkomponenten befanden sich in C #, aber die Berechnungsmaschine wurde in F # geschrieben.

Die Verwendung von F # zur Bewältigung der Komplexität im Herzen dieser Anwendung zeigt deutlich einen Sweet Spot für die Sprache in Unternehmenssoftware, nämlich die algorithmisch komplexe Analyse großer Datenmengen. Meine Erfahrung war sehr positiv. Bestimmtes:

Maßeinheiten Die Branche, in der ich arbeite, ist mit Einheiten übersät. Die von mir implementierten Gleichungen (oft geometrischer Natur) befassten sich mit Zeit-, Kraft- und Energieeinheiten. Es ist eine enorme Zeitersparnis, wenn das Typsystem die Richtigkeit der Einheiten der Ein- und Ausgänge von Funktionen überprüft, sowohl beim Testen als auch beim Lesen / Verstehen des Codes. Es beseitigt eine ganze Klasse von Fehlern, für die frühere Systeme anfällig waren.

Explorative Programmierung Durch die Arbeit mit Skriptdateien und REPL (F # Interactive) konnte ich den Lösungsbereich effektiver erkunden, bevor ich mich zu einer Implementierung entschied, als mit der herkömmlichen Schleife zum Bearbeiten / Kompilieren / Ausführen / Testen. Es ist eine sehr natürliche Möglichkeit für einen Programmierer, sein Verständnis für das Problem und die Spielspannungen im Spiel zu entwickeln.

Unit-Test Code, der mit nicht nebenwirkenden Funktionen und unveränderlichen Datenstrukturen geschrieben wurde, ist eine Freude zu testen. Es gibt keine komplexen zeitabhängigen Interaktionen, um Dinge zu vermasseln, oder große Mengen von Abhängigkeiten, die verspottet werden müssen.

Interoperation Ich habe die Schnittstelle zur Berechnungsmaschine in C # definiert und die Berechnung in F # implementiert. Die Berechnungs-Engine könnte dann in jedes C # -Modul eingefügt werden, das sie verwenden muss, ohne dass Bedenken hinsichtlich der Interoperabilität bestehen. Nahtlos. Der C # -Programmierer muss es nie wissen.

Code-Reduktion Ein Großteil der in die Berechnungsmaschine eingegebenen Daten lag in Form von Vektoren und Matrizen vor. Funktionen höherer Ordnung essen diese zum Frühstück mit minimalem Aufwand und minimalem Code. Wunderschönen.

Fehlende Fehler Die funktionale Programmierung kann sich seltsam anfühlen. Ich kann an einem Algorithmus arbeiten und mich bemühen, den Code dazu zu bringen, die Typprüfung zu bestehen, aber sobald die Typprüfung zufrieden ist, funktioniert es. Es ist fast binär, entweder wird es nicht kompiliert oder es ist korrekt. Seltsame Randfallfehler werden minimiert, Rekursion und Funktionen höherer Ordnung entfernen viel Buchhaltungscode, der Randfallfehler einführt.

Parallelität Die funktionale Reinheit der resultierenden Implementierung macht es reif, die inhärente Parallelität bei der Verarbeitung von Datenvektoren auszunutzen. Vielleicht gehe ich jetzt als nächstes dorthin, wo .NET 4 herauskommt.

Simon Cousins
quelle
18
+1, um zu erklären, warum F # für Motoren mit Zahlenverarbeitung sehr gut geeignet ist. Eine weitere (virtuelle) +1 zur Angabe von Maßeinheiten. Dieser Teil der Sprache verdient es, öfter erwähnt zu werden.
Siehe
5
Tolle Antwort, relevant, zeitgemäß und skizziert F # Eignung für den Umgang mit Komplexität, ich habe viel aus dem Lesen gelernt, danke
Peter McG
Tolle Antwort Simon, und wie Don gestern Abend erwähnte, zitiert in seinen letzten Folien. Zeit, einen Link "In den Warenkorb" hinzuzufügen?
Chris Ballard
1
Hallo, darfst du uns mehr über deine Apps-Architektur erzählen?
Nikos
76

Während meines Praktikums bei Microsoft Research habe ich an einigen Teilen von Visual Studio IntelliSense für F # gearbeitet (das selbst in F # geschrieben ist). Ich hatte bereits einige Erfahrungen mit IntelliSense aus früheren C # -Projekten, daher denke ich, dass ich die beiden vergleichen kann.

  • Visual Studio Extensibility basiert immer noch auf COM, daher müssen Sie sich mit Objekten befassen, die keine sehr schönen .NET-Objekte sind (und definitiv nicht funktionieren), aber ich glaube nicht, dass es einen wesentlichen Unterschied zwischen C # und F # gibt (es funktioniert reibungslos von F #)

  • Die Datenstrukturen, die zur Darstellung von Programmcode in F # verwendet werden, sind meist diskriminierte Gewerkschaften (die in C # in keiner vernünftigen Weise unterstützt werden). Dies macht einen großen Unterschied für diese Art von Anwendung (bei der Sie Baumstrukturen wie Programmcode verarbeiten müssen) ). Durch diskriminierte Gewerkschaften und Mustervergleiche können Sie den Code besser strukturieren (verwandte Funktionen an einem Ort aufbewahren, anstatt sie in virtuellen Methoden überall zu haben).

Zuvor habe ich auch am CodeDOM-Anbieter für F # gearbeitet (auch in F # geschrieben). Ich habe tatsächlich zuerst in C # experimentiert, dann aber den Code in F # konvertiert.

  • Der CodeDOM-Anbieter muss eine Struktur durchlaufen, die mit .NET-Objekten dargestellt wird, sodass nicht viel Platz zum Erfinden eigener Darstellungen von Daten vorhanden ist (in diesem Bereich kann F # nützliche Vorteile bieten).

  • Es gab jedoch viele kleine F # -Funktionen, die die Aufgabe erleichterten. Da Sie eine Zeichenfolge erstellen müssen, habe ich benutzerdefinierte Operatoren zum Erstellen von Zeichenfolgen (mithilfe StringBuilder) definiert und den Code mithilfe dieser und Funktionen höherer Ordnung (z. B. zum Formatieren einer Liste von Objekten, die durch die angegebene Zeichenfolge getrennt wurden usw.) implementiert, wodurch viele entfernt wurden Wiederholung (und langwierige foreachSchleifen).

Dies sind zwei relativ spezifische Beispiele, aber beide beziehen sich auf die Arbeit mit Darstellungen von Programmen oder Ausdrücken oder allgemeiner auf komplexe baumartige Datenstrukturen. Ich denke, dass in diesem Bereich F # definitiv eine gute Wahl ist (unabhängig von den Funktionsmerkmalen in C #).

Tomas Petricek
quelle
6
Sehr interessant, mehr Beweise dafür, dass die Akzeptanz von F # bei Microsoft sicherlich hoch ist, was für ein großartiges Praktikum das gewesen sein muss!
Peter McG
43

Wir haben das weltweit erste kommerzielle Produkt in F # ( F # für Visualisierung ) und das zweite ( F # für Numerik ) sowie die erste kommerzielle Literatur zu F # ( The F # .NET Journal ) ausgeliefert und das einzige Buch über die aktuelle Version geschrieben und veröffentlicht von F # ( Visual F # 2010 für Technical Computing ).

Wir hatten Produkte in ähnlicher Weise versendet, die in C # geschrieben waren (z. B. dieses ), aber wir hatten auch einen starken Hintergrund in der kommerziellen Verwendung von OCaml. Wir waren begeisterte Erstanwender von F #, als es 2006 noch ein Forschungsprototyp war, weil wir das Potenzial einer anständigen modernen OCaml-ähnlichen Sprache auf der industrietauglichen .NET-Plattform erkannten und uns daher für eine Produktproduktion einsetzten. Das Ergebnis war ein unglaublicher Erfolg und F # hat unsere hohen Erwartungen weit übertroffen.

Für uns hat F # viele verschiedene Vorteile und wir verwenden es für eine Vielzahl von Anwendungen. Wir haben Hunderttausende von Zeilen F # -Code in der Produktion. Wir verwenden jetzt F # für alle unsere LOB-Apps: Unsere Kreditkartentransaktionen werden mit F # -Code verarbeitet, unsere Produktbenachrichtigungen werden mit F # -Code gesendet, unsere Abonnements werden mit F # -Code abgewickelt, unsere Konten werden mit F # -Code erstellt und so weiter. Vielleicht ist das wichtigste Sprachmerkmal, das sich hier auszahlt, der Mustervergleich. Wir haben sogar F # verwendet, um die Farbsyntax unseres neuesten Buches hervorzuheben ...

Unsere Visualisierungsbibliothek ist ein Verkaufsschlager und ihre Funktionalität konzentriert sich auf die interaktive Ausführung von F # in Visual Studio. Unsere Bibliothek erweitert dies um die Möglichkeit, interaktive 2D- und 3D-Visualisierungen mit minimalem Aufwand (z. B. nur) zu erstellenPlot([Function sin], (-6., 6.))eine Sinuswelle zeichnen). Insbesondere sind alle Threading-Probleme vollständig automatisiert, sodass sich Benutzer nicht um UI-Threads und den Versand kümmern müssen. Erstklassige Funktionen und Faulheit waren beim Schreiben dieses Teils der Bibliothek äußerst wertvoll, und algebraische Datentypen wurden an anderer Stelle ausgiebig verwendet. Die vorhersehbare Leistung erwies sich auch hier als wertvoll, als unsere Kunden bei den WPF-Treffertests auf Leistungsfehler stießen und den relevanten Code in F # problemlos erneut implementieren konnten, um eine 10.000-fache Leistungsverbesserung zu erzielen. Aufgrund der Freiform der Benutzeroberfläche dieses Produkts wären der GUI-Designer und C # nicht vorteilhaft gewesen.

Ein Großteil unserer Arbeit dreht sich um numerische Methoden, einschließlich unserer kommerziellen Bibliotheken und Bücher. F # ist in diesem Bereich viel stärker als C #, da es Abstraktionen auf hoher Ebene (z. B. Funktionen höherer Ordnung) mit minimalen Leistungseinbußen bietet. Unser überzeugendstes Ergebnis in diesem Zusammenhang war die Erstellung einer einfachen, aber verallgemeinerten Implementierung der QR-Zerlegung aus der linearen Algebra, die 20-mal kürzer als der Fortran-Code aus der Referenzimplementierung von LAPACK war und bis zu 3-mal schneller als die vom Hersteller optimierte Intel Math Kernel Library und allgemeiner, weil unser Code Matrizen aller Art verarbeiten kann, sogar symbolische Matrizen!

Wir entwickeln derzeit WPF / Silverlight-Komponenten in einer Mischung aus F # (für den Mut) und C # (für die Unterlegscheibe), erstellen WPF-Apps, die als interaktive Handbücher für unsere Softwareprodukte dienen, und ich schreibe ein neues Buch, Multicore F # wird der endgültige Leitfaden für die parallele Programmierung mit gemeinsamem Speicher unter .NET sein.

Jon Harrop
quelle
Sind Sie derselbe Jon Harrop, der "F # for Scientists" geschrieben hat?
Andre Artus
7
Ja. Ich habe vor 5 Jahren F # für Wissenschaftler geschrieben.
Jon Harrop
Haben Sie eine Art Referenz für den QR-Zerlegungscode in F #, die Sie in Ihrem vorletzten Absatz erwähnt haben? Vielen Dank.
Samik R
@ SamikR: Nein, sorry. Das ist Handelscode. Es war jedoch leicht zu schreiben.
Jon Harrop
@Jon irgendein Wort auf Multicore F #?
Professor Bigglesworth
25

In den letzten 6 Monaten habe ich an einer Vim-Emulationsebene für Visual Studio 2010 gearbeitet. Es ist ein kostenloses Produkt mit allen Quellen, die auf Github frei verfügbar sind

Das Projekt ist in 3 DLLs unterteilt, die eine bestimmte Ebene darstellen. Jede Schicht hat eine entsprechende Unit-Test-DLL.

  1. Vim Motor: F #
  2. WPF-Ebene für Verzierungen und Editorintegration: C #
  3. Visual Studio-Integrationsschicht: C #

Dies ist das erste große Projekt, das ich jemals mit F # gemacht habe und ich muss sagen, dass ich die Sprache liebe. In vielerlei Hinsicht habe ich dieses Projekt als Methode zum Lernen von F # verwendet (und diese Lernkurve ist sehr offensichtlich, wenn Sie sich die Geschichte des Projekts ansehen).

Was ich an F # am erstaunlichsten finde, ist, wie prägnant eine Sprache ist. Die Vim-Engine macht den Großteil der Logik aus, macht jedoch nur 30% der gesamten Codebasis aus.

JaredPar
quelle
19
Editor ... funktionale Sprache ... vi Emulation ... Sie haben Emacs neu erfunden. NOOOOOOOOOOOOOOOOOOOOOO!
Ben Voigt
2
Außer dass es "100% ohne Klammern zertifiziert" ist :)
Pavel Minaev
@ Pavel, außer natürlich Tupel und .net-Methodenaufrufe
JaredPar
26
Zwei Dinge, die hier zu beachten sind. Erstens brauchen Tupel ()in F # nicht - der ,Operator erstellt sie, also let x = 1,2ist ein gültiges Tupel bereits ohne Parens. Zweitens können alle Paar-Parens in F # durch Paare von begin.. ersetzt werden end(dies wird von ML geerbt) - dies ist beispielsweise "foo".IndexOf begin 'a', 1 endein gültiger .NET-Methodenaufruf. Also, wenn Sie jemals parensfrei sein wollten, ist F # eine Sprache, die es Ihnen ermöglicht, genau das zu tun :)
Pavel Minaev
Lustiger Kommentar Pavel! Wusste das nicht. Ich denke , dass in einigen Fällen mit großer Gruppierung blockiert, könnte ich eigentlich lieber begin.. end. AUCH: VsVim REGELN!
Dan Fitch
13

Viele der Komponententests für die F # Visual Studio-Komponenten sind in F # geschrieben. Sie laufen außerhalb von VS und verspotten die verschiedenen Visual Studio-Bits. Die Möglichkeit, anonyme Objekte zu konsultieren, die Schnittstellen implementieren, ist anstelle eines spöttischen Frameworks / Tools nützlich. Ich kann einfach schreiben

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 )

wenn ich brauche eine Instanz eines von zB IVsOutputWindowPanezu einer anderen Komponente zu übergeben , die schließlich Aufruf werden OutputStringund Clearund dann das Einsicht string list refam Ende des Testobjekts zu sehen , ob die erwartete Ausgabe geschrieben wurde.

Brian
quelle
Interessante, mehr Beweise dafür, dass die Akzeptanz von F # in Microsoft sicherlich hoch ist. Ich wusste nicht, dass Sie anonyme Objekte erstellen können, die Schnittstellen in F # implementieren
Peter McG
9

Wir haben eine benutzerdefinierte Regelengine mit der Lex-Yacc-Implementierung in F # geschrieben

BEARBEITEN, um eine Kommentarantwort einzuschließen

Es gab keine Lex / Yacc-Implementierung in C #. (Soweit uns bekannt war und die F # eins war)

Es wäre möglich gewesen, aber ein regelrechter Schmerz, das Parsen selbst aufzubauen.

Dieses Thema zeigt einige andere Vorschläge, wie z. B. externe Bibliotheken, aber unser leitender Architekt ist ein alter Hase in funktionalen Sprachen, sodass die Wahl von F # ein Kinderspiel war.

Johnc
quelle
+1 Sie hätten dies zuvor in C # geschrieben. War es aus einem bestimmten Grund ungeeignet oder langsamer?
Peter McG
@Peter McGrattan Zumindest zum Zeitpunkt des Schreibens (der Software) gab es keine Lex / Yacc-Implementierung in C #. Es wäre möglich gewesen, aber ein regelrechter Schmerz, das Parsen selbst aufzubauen. stackoverflow.com/questions/540593/lex-yacc-for-c zeigt einige andere Vorschläge, aber unser leitender Architekt ist ein alter Hase in funktionalen Sprachen, so dass die Wahl, F # zu verwenden, ein Kinderspiel war
Johnc
Wenn Sie dachten, es gäbe kein Lex / Yacc für C # Ich fürchte, Sie haben einfach nicht genau genug danach gesucht (es gibt eines, das älter als F # ist), das sagte, wenn Sie Lex / Yacc brauchen, ist F # meiner Meinung nach viel besser geeignet Hammer für diesen Nagel als c #
Rune FS
Ich habe F # mit fslex / fxyacc selbst verwendet, allerdings nicht in einem "Produktions" -Projekt (ohnehin noch nicht veröffentlicht) - Hervorhebung der MSIL-Syntax und Erweiterung der Code-Vervollständigung für VS. Der Hauptvorteil der Verwendung von F # besteht darin, dass Sie ADTs erhalten, die sehr praktisch sind, um Analysebäume darzustellen. Die Verwendung von Reißverschlüssen ( en.wikipedia.org/wiki/Zipper_(data_structure) ) erleichtert das inkrementelle Lexing - und funktionale Reißverschlüsse lassen sich in F # einfacher präzise bearbeiten.
Pavel Minaev
7

Ich arbeite derzeit an einer Kompilierung für eine Programmiersprache. Der Compiler ist vollständig in F # geschrieben. Der Compiler (abgesehen vom Lex- und Parser-Build mit lex / yacc) wird im Grunde genommen als viel Transformation einer komplexen baumartigen Struktur erstellt.

Wie von anderen festgestellt, diskriminieren Gewerkschaften und Mustervergleich macht das Arbeiten mit dieser Art von Datenstruktur viel einfacher, als den Code in virtuellen Methoden "überall" abzulegen.

Ich hatte keine F # -Arbeit erledigt, bevor ich anfing, am Compiler zu arbeiten (ich hatte jedoch Compiler in einer anderen OCaml-Variante namens MoscowML), und genau wie Jared angibt, ist aus dem Code ersichtlich, welche Teile ich zuerst gemacht habe, aber im Allgemeinen fand ich F # einfach Es wird allerdings etwas länger dauern, bis man wieder in die FP-Denkweise eintaucht, nachdem man ein Jahrzehnt lang hauptsächlich OO codiert hat.

Abgesehen von der Arbeit mit Bäumen finde ich die Fähigkeit, deklarativen Code zu schreiben, der Hauptvorteil von FP (einschließlich F #) mit Code, der den Algorithmus beschreibt. Ich versuche zu implementieren, im Gegensatz zu C #, das beschreibt, wie ich den Algorithmus implementiert habe, ist ein großer Vorteil.

Rune FS
quelle
6

Keine persönliche Erfahrung, aber Sie können sich eine Folge von DNR anhören (ich denke, es ist diese ), in der sie mit Microsoft-Leuten über F # sprechen. Sie haben den größten Teil des Xbox Live-Bewertungssystems, das alles andere als trivial war, mit F # geschrieben. Das System skalierte massiv über Hunderte von Maschinen und sie waren sehr zufrieden damit.

Igor Zevaka
quelle
5

Ich weiß nicht, ob es in Produktion ist, aber die KI für "The Path of Go" wurde in F # geschrieben:

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

The Path of Go: Ein Microsoft-Forschungsspiel für Xbox 360

Diese Demo zeigt ein Xbox 360-Spiel, das auf dem Go-Spiel basiert und bei Microsoft Research Cambridge im eigenen Haus produziert wurde. Go ist eines der bekanntesten Brettspiele in Ostasien. Es entstand vor 4000 Jahren in China. Hinter der täuschenden Einfachheit des Spiels verbirgt sich eine große Komplexität. Das Lernen dauert nur wenige Minuten, aber das Meistern dauert ein Leben lang. Obwohl Computer bei Chess die menschlichen Fähigkeiten übertroffen haben, bleibt die Implementierung einer wettbewerbsfähigen KI für Go eine Forschungsherausforderung. Das Spiel basiert auf drei Technologien, die bei Microsoft Research Cambridge entwickelt wurden: einer KI, die Go, die F # -Sprache und TrueSkill ™ für Online-Spieler spielen kann. Die KI ist in F # implementiert und erfüllt die Herausforderung, im .net compact Framework auf Xbox 360 effizient zu arbeiten. Dieses Spiel versetzt Sie in eine Reihe von visuell atemberaubenden 3D-Szenen. Es wurde vollständig in verwaltetem Code unter Verwendung der XNA-Umgebung entwickelt.

(Jemand anderes hat "TrueSkill" bereits erwähnt.)

Brian
quelle
Faszinierend: F # läuft auf dem kompakten Framework der XBox. Verweist FSharp.Core.dll nicht zusammen mit FSharp.Core.optdata FSharp.Core.sigdata auf Nicht-CF-Assemblys?
Peter McG
1
Das CTP wird mit einem separaten FSharp.Core geliefert, der für .NETCF erstellt wurde. (Es gibt auch einen separaten FSharp.Core für Silverlight.)
Brian
Von was für einem CTP sprechen Sie?
Jwosty