Dans quels domaines l'utilisation de F # pourrait-elle être plus appropriée que C #? [fermé]


210

Au cours des dernières années, F # est devenu l'un des langages entièrement pris en charge par Microsoft, utilisant de nombreuses idées incubées dans OCaml, ML et Haskell.

Au cours des dernières années, C # a étendu ses fonctionnalités générales en introduisant de plus en plus de fonctionnalités de langage fonctionnel: LINQ (compréhension de liste), Lambdas, fermetures, délégués anonymes et plus ...

Compte tenu de l'adoption par C # de ces fonctionnalités et de la taxonomie de F # en tant que langage fonctionnel impur (il vous permet d'accéder aux bibliothèques du framework ou de changer l'état partagé lorsqu'une fonction est appelée si vous le souhaitez), il existe une forte similitude entre les deux langages bien que chacun ait ses propre accent primaire polaire opposé.

Je suis intéressé par tous les modèles réussis utilisant ces deux langues dans vos programmes de production polyglottes ainsi que par les domaines des logiciels de production (applications Web, applications clientes, applications serveur) que vous avez écrits en F # au cours de la dernière année, ou que vous auriez auparavant écrit en C #.

Réponses:


258

J'ai écrit une demande pour équilibrer le calendrier national de production d'électricité d'un portefeuille de centrales électriques et une position commerciale pour une société d'énergie. Les composants client et serveur étaient en C # mais le moteur de calcul a été écrit en F #.

L'utilisation de F # pour répondre à la complexité au cœur de cette application démontre clairement un sweet spot pour le langage dans les logiciels d'entreprise, à savoir l'analyse algorithmiquement complexe de grands ensembles de données. Mon expérience a été très positive. En particulier:

Unités de mesure L'industrie dans laquelle je travaille est jonchée d'unités. Les équations que j'ai mises en œuvre (souvent de nature géométrique) traitaient des unités de temps, de puissance et d'énergie. Faire vérifier par le système de typage l'exactitude des unités des entrées et sorties des fonctions est un gain de temps énorme, tant en termes de test que de lecture / compréhension du code. Il supprime toute une classe d'erreurs auxquelles les systèmes précédents étaient sujets.

Programmation exploratoire Travailler avec des fichiers de script et le REPL (F # Interactive) m'a permis d'explorer l'espace de la solution plus efficacement avant de s'engager dans une implémentation que la boucle d'édition / compilation / exécution / test plus traditionnelle. C'est un moyen très naturel pour un programmeur de développer sa compréhension du problème et des tensions de conception en jeu.

Test unitaire Le code écrit à l'aide de fonctions sans effet secondaire et de structures de données immuables est un plaisir à tester. Il n'y a pas d'interactions complexes dépendant du temps pour bousiller les choses ou de grands ensembles de dépendances à moquer.

Interopérabilité J'ai défini l'interface avec le moteur de calcul en C # et implémenté le calcul en F #. Le moteur de calcul pourrait ensuite être injecté dans n'importe quel module C # qui devait l'utiliser sans aucun souci d'interopérabilité. Sans couture. Le programmeur C # n'a jamais besoin de savoir.

Réduction du code La plupart des données introduites dans le moteur de calcul étaient sous forme de vecteurs et de matrices. Les fonctions d'ordre supérieur les mangent pour le petit déjeuner avec un minimum d'agitation, un code minimal. Belle.

Manque de bugs La programmation fonctionnelle peut sembler étrange. Je peux travailler sur un algorithme, en essayant de faire en sorte que le code passe le vérificateur de type, mais une fois que le vérificateur de type est satisfait, cela fonctionne. Son presque binaire, soit il ne compilera pas ou son correct. Les erreurs de cas de bord étranges sont minimisées, la récursivité et les fonctions d'ordre supérieur suppriment beaucoup de code de comptabilité qui introduit des erreurs de cas de bord.

Parallélisme La pureté fonctionnelle de l'implémentation résultante le rend mûr pour exploiter le parallélisme inhérent au traitement des vecteurs de données. C'est peut-être là que j'irai maintenant maintenant que .NET 4 est sorti.


18
+1 pour expliquer pourquoi F # est très adapté aux moteurs de calcul de nombres. Un autre (virtuel) +1 pour mentionner les unités de mesure. Cette partie du langage mérite d'être mentionnée plus souvent.
cfern

5
Excellente réponse, pertinente, contemporaine et décrivant l'aptitude F # à gérer la complexité, j'ai beaucoup appris en la lisant, merci
Peter McG

Excellente réponse Simon, et comme Don l'a mentionné hier soir, cité dans ses récentes diapositives. Il est temps d'ajouter un lien "ajouter au panier"?
Chris Ballard

1
salut, avez-vous le droit de nous en dire plus sur l'architecture de vos applications?
Nikos

76

Pendant mon stage chez Microsoft Research, j'ai travaillé sur certaines parties de Visual Studio IntelliSense pour F # (qui est lui-même écrit en F #). J'avais déjà une certaine expérience avec IntelliSense des projets C # précédents, donc je pense que je peux comparer les deux.

  • L'extensibilité de Visual Studio est toujours basée sur COM, vous devez donc traiter des objets qui ne sont pas de très bons objets .NET (et certainement pas fonctionnels), mais je ne pense pas qu'il y ait de différence majeure entre C # et F # (cela fonctionne bien de F #)

  • Les structures de données utilisées pour représenter le code de programme en F # sont principalement des unions discriminées (qui ne sont pas prises en charge en C # de manière raisonnable) et cela fait une énorme différence pour ce type d'application (où vous devez traiter des structures d'arborescence, telles que le code de programme ). Les unions discrètes et la correspondance de modèles vous permettent de mieux structurer le code (conservez les fonctionnalités associées au même endroit plutôt que de les avoir partout dans les méthodes virtuelles)

Plus tôt, j'ai également travaillé sur le fournisseur CodeDOM pour F # (également écrit en F #). J'ai fait des premières expériences en C #, mais j'ai ensuite converti le code en F #.

  • Le fournisseur CodeDOM doit traverser une structure représentée à l'aide d'objets .NET, donc il n'y a pas beaucoup d'espace pour inventer vos propres représentations de données (qui est le domaine où F # peut offrir de beaux avantages).

  • Cependant, il existe de nombreuses petites fonctionnalités F # qui facilitent la tâche. Étant donné que vous devez produire une chaîne, j'ai défini des opérateurs personnalisés pour créer des chaînes (à l'aide StringBuilder) et implémenté le code en les utilisant et des fonctions d'ordre supérieur (par exemple pour formater la liste des objets séparés à l'aide de la chaîne spécifiée, etc.), ce qui a supprimé beaucoup de répétition (et foreachboucles fastidieuses ).

Ce sont deux exemples relativement spécifiques, mais tous deux sont liés à l'utilisation de représentations de programmes, ou d'expressions, ou plus généralement, de structures de données arborescentes complexes. Je pense que dans ce domaine, F # est définitivement un bon choix (quelles que soient les fonctionnalités en C #).


6
Très intéressant, plus de preuves que l'adoption de F # au sein de Microsoft est certainement élevée, quel super stage qui a dû être!
Peter McG

43

Nous avons expédié le premier produit commercial au monde écrit en F # ( F # pour la visualisation ) et le second ( F # pour la numérisation ) ainsi que la première littérature commerciale sur F # ( The F # .NET Journal ) et écrit et publié le seul livre sur la version actuelle de F # ( Visual F # 2010 for Technical Computing ).

Nous avions expédié des produits sur des lignes similaires écrites en C # (par exemple ceci ) mais nous avions également une solide expérience dans l'utilisation commerciale d'OCaml. Nous avons été les premiers à adopter avec enthousiasme le F # alors qu'il était encore un prototype de recherche en 2006, car nous avons reconnu le potentiel d'avoir un langage OCaml moderne décent sur la plate-forme .NET de puissance industrielle et, par conséquent, nous avons poussé à le faire produire. Le résultat a été un succès incroyable et F # a largement dépassé nos attentes élevées.

Pour nous, F # présente de nombreux avantages différents et nous l'utilisons pour une grande variété d'applications. Nous avons des centaines de milliers de lignes de code F # en production. Nous utilisons maintenant F # pour toutes nos applications LOB: nos transactions par carte de crédit sont traitées en utilisant le code F #, nos notifications de produits sont envoyées en utilisant le code F #, nos abonnements sont traités en utilisant le code F #, nos comptes sont effectués en utilisant le code F # et ainsi de suite. Peut-être que la principale caractéristique du langage qui paie des dividendes est la correspondance de modèles. Nous avons même utilisé F # pour mettre en évidence la syntaxe des couleurs de notre dernier livre ...

Notre bibliothèque de visualisation est un gros vendeur et ses fonctionnalités se concentrent sur l'exécution interactive de F # dans Visual Studio. Notre bibliothèque augmente cela avec la possibilité de générer des visualisations interactives 2D et 3D avec un minimum d'effort (par exemple justePlot([Function sin], (-6., 6.))pour tracer une onde sinusoïdale). En particulier, tous les problèmes de thread sont entièrement automatisés afin que les utilisateurs n'aient pas à se soucier des threads d'interface utilisateur et de la répartition. Les fonctions de première classe et la paresse étaient extrêmement précieuses lors de l'écriture de cette partie de la bibliothèque et les types de données algébriques ont été largement utilisés ailleurs. Les performances prévisibles se sont également révélées précieuses ici lorsque nos clients ont rencontré des bogues de performances dans les tests de réussite de WPF et ont facilement pu réimplémenter le code correspondant en F # pour une amélioration de 10 000 × des performances. En raison de la nature libre de l'interface graphique de ce produit, le concepteur de l'interface graphique et C # n'auraient pas été bénéfiques.

Une grande partie de notre travail s'articule autour des méthodes numériques, y compris nos bibliothèques commerciales et nos livres. F # est beaucoup plus puissant dans ce domaine que C # car il offre des abstractions de haut niveau (par exemple des fonctions d'ordre supérieur) avec des pénalités de performances minimales. Notre résultat le plus convaincant dans ce contexte a été la création d'une implémentation simple mais généralisée de la décomposition QR à partir de l'algèbre linéaire qui était 20 × plus courte que le code Fortran à partir de l'implémentation de référence de LAPACK, jusqu'à 3 × plus rapide que le processeur Intel Math Bibliothèque du noyau et plus générique car notre code peut gérer des matrices de tout type, même des matrices symboliques!

Nous développons actuellement des composants WPF / Silverlight dans un mélange de F # (pour les tripes) et C # (pour le shim), construisant des applications WPF pour agir comme des manuels interactifs pour nos produits logiciels et j'écris un nouveau livre, Multicore F #, qui sera le guide définitif de la programmation parallèle en mémoire partagée sur .NET.


Êtes-vous le même Jon Harrop qui a écrit "F # for Scientists"?
Andre Artus

7
Oui. J'ai écrit F # for Scientists il y a 5 ans.
Jon Harrop

Avez-vous une sorte de référence pour le code de décomposition QR en F # que vous mentionnez dans votre avant-dernier paragraphe? Merci.
Samik R

@SamikR: Non, désolé. C'est du code commercial. C'était facile à écrire cependant.
Jon Harrop

@Jon mot sur Multicore F #?
professeur bigglesworth

25

Au cours des 6 derniers mois, j'ai travaillé sur une couche d'émulation Vim pour Visual Studio 2010. C'est un produit gratuit avec toutes les sources, il est disponible gratuitement sur github

Le projet est divisé en 3 DLL représentant une couche distincte. Chaque couche a une DLL de test unitaire correspondante.

  1. Moteur Vim: F #
  2. Couche WPF pour les ornements et l'intégration de l'éditeur: C #
  3. Couche d'intégration Visual Studio: C #

C'est le premier projet majeur que j'ai jamais réalisé avec F # et je dois dire que j'aime la langue. À bien des égards, j'ai utilisé ce projet comme méthode d'apprentissage de F # (et cette courbe d'apprentissage est très évidente si vous regardez à travers l'histoire du projet).

Ce que je trouve le plus étonnant à propos de F #, c'est à quel point il est concis d'un langage. Le moteur Vim comprend la majeure partie de la logique, mais il ne représente que 30% de la base de code globale.


19
Éditeur ... langage fonctionnel ... émulation vi ... vous avez réinventé emacs. NOOOOOOOOOOOOOOOOOOOOOOO!
Ben Voigt

2
Sauf que c'est "Certifié 100% sans parenthèses" :)
Pavel Minaev

@Pavel, sauf pour les tuples bien sûr, et les appels de méthode .net
JaredPar

26
Deux choses à noter ici. Tout d'abord, les tuples n'ont pas besoin ()en F # - c'est l' ,opérateur qui les crée, tout let x = 1,2comme un tuple valide sans parens. Deuxièmement, toute paire de parens en F # peut être remplacée par des paires de begin.. end(ceci est hérité de ML) - ainsi, par exemple, "foo".IndexOf begin 'a', 1 endest un appel de méthode .NET valide. Donc, si vous avez toujours voulu être sans parens, F # est une langue qui vous permet de faire exactement cela :)
Pavel Minaev

Commentaire drôle Pavel! Je ne le savais pas. Je pense que dans certains cas , avec de grands blocs de regroupement, je pourrais en fait préférer begin.. end. AUSSI: RÈGLES VsVim!
Dan Fitch

13

De nombreux tests unitaires pour les composants F # Visual Studio sont écrits en F #. Ils s'exécutent en dehors de VS, se moquant des différents bits de Visual Studio. La possibilité de contrer des objets anonymes qui implémentent des interfaces est utile à la place d'un framework / outil moqueur. Je peux juste écrire

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 )

lorsque j'ai besoin d'une instance, par exemple d'un, IVsOutputWindowPanepour passer à un autre composant qui finira par appeler OutputStringet Clear, puis inspecter l' string list refobjet à la fin du test pour voir si la sortie attendue a été écrite.


Intéressant, plus de preuves que l'adoption de F # au sein de Microsoft est certainement élevée. Je ne savais pas que vous pouviez créer des objets anonymes qui implémentent des interfaces en F #
Peter McG

9

Nous avons écrit un langage de moteur de règles personnalisé en utilisant l'implémentation Lex-Yacc en F #

MODIFIER pour inclure la réponse au commentaire

Il n'y avait pas d'implémentation lex / yacc en C #. (à notre connaissance, et le F # était)

Cela aurait été possible, mais une véritable douleur de construire l'analyse nous-mêmes.

Cette rubrique montre quelques autres suggestions, telles que les bibliothèques externes, mais notre architecte principal est un vieux maître des langages fonctionnels, donc le choix d'utiliser F # était une évidence.


+1 Vous auriez déjà écrit ceci en C # était-ce inapproprié ou plus lent pour une certaine raison?
Peter McG

@Peter McGrattan Au moins au moment de la rédaction (le logiciel), il n'y avait pas d'implémentation lex / yacc en C #. Cela aurait été possible, mais une véritable douleur de construire l'analyse nous-mêmes. stackoverflow.com/questions/540593/lex-yacc-for-c montre quelques autres suggestions, mais notre architecte principal est un ancien des langages fonctionnels, donc le choix d'utiliser F # était une évidence
johnc

si vous pensiez qu'il n'y avait pas de lex / yacc pour C #, je crains que vous ne cherchiez tout simplement pas assez fort pour cela (il y en a un plus ancien que F #) qui a dit que si vous avez besoin de lex / yacc F # est à mon avis un bien mieux adapté marteau pour cet ongle que c #
Rune FS

J'ai utilisé F # avec fslex / fxyacc moi-même, mais pas dans un projet de "production" (pas encore sorti, de toute façon) - Mise en évidence de la syntaxe MSIL et extension de complétion de code pour VS. Le principal avantage de l'utilisation de F # est que vous obtenez des ADT, qui sont très pratiques pour représenter les arbres d'analyse. De plus, l'utilisation de fermetures à glissière ( en.wikipedia.org/wiki/Zipper_(data_structure) ) facilite la lexing incrémentiel - et les fermetures à glissière, étant fonctionnelles, sont plus faciles à manipuler de manière concise en F #.
Pavel Minaev

7

Je travaille actuellement sur une compilation pour un langage de programmation. Le compilateur est entièrement écrit en F #. Le compilateur (à part la construction de lex et de l'analyseur avec lex / yacc) est essentiellement construit comme beaucoup de transformation d'une structure complexe comme un arbre.

Comme indiqué par d'autres, les unions discriminantes et la correspondance de modèles rendent le travail avec ce type de structure de données beaucoup plus facile que de vider le code dans des méthodes virtuelles "partout".

Je n'avais pas fait de travail en F # avant de commencer à travailler sur le compilateur (j'avais cependant des compilateurs volumineux dans une autre variante OCaml appelée MoscowML) et tout comme Jared déclare qu'il est visible dans le code quelles parties j'ai fait en premier mais en général j'ai trouvé F # facile apprendre à se remettre dans l'esprit de FP après avoir codé principalement OO pendant une décennie prendra un peu plus de temps.

en travaillant avec des arbres, je trouve que la possibilité d'écrire du code déclaratif est le principal avantage de FP (F # inclus) ayant un code qui décrit l'algorithme que j'essaie d'implémenter contrairement à C # décrivant comment j'ai implémenté l'algortihm est un énorme avantage.


6

Pas une expérience personnelle, mais vous pouvez écouter un épisode de DNR (je pense que c'est celui-ci ) où ils parlent à F folk de Microsoft. Ils ont écrit la plupart du système de notation Xbox Live, qui était loin d'être trivial, en utilisant F #. Le système a évolué massivement sur des centaines de machines et ils en étaient très satisfaits.


5

Je ne sais pas s'il est en production, mais l'IA de "The Path of Go" a été écrite en F #:

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

The Path of Go: un jeu de recherche Microsoft pour Xbox 360

Cette démo présente un jeu Xbox 360, basé sur le jeu de Go, produit en interne chez Microsoft Research Cambridge. Go est l'un des jeux de société les plus célèbres d'Asie de l'Est, il est né en Chine il y a 4000 ans. Derrière la simplicité trompeuse du jeu se cache une grande complexité. Cela ne prend que quelques minutes pour apprendre, mais il faut une vie pour maîtriser. Bien que les ordinateurs aient dépassé les compétences humaines aux échecs, la mise en œuvre d'une IA compétitive pour Go reste un défi de recherche. Le jeu est propulsé par trois technologies développées à Microsoft Research Cambridge: une IA capable de jouer à Go, le langage F # et TrueSkill ™ pour correspondre aux joueurs en ligne. L'IA est implémentée en F # et relève le défi de fonctionner efficacement dans le cadre compact .net sur Xbox 360. Ce jeu vous place dans un certain nombre de scènes 3D visuellement époustouflantes. Il a été entièrement développé en code managé en utilisant l'environnement XNA.

(Quelqu'un d'autre a déjà mentionné "TrueSkill".)


Fascinant: F # fonctionnant sur le framework compact sur XBox. FSharp.Core.dll avec FSharp.Core.optdata FSharp.Core.sigdata ne fait-il pas référence à des assemblys non CF?
Peter McG

1
Le CTP est livré avec un FSharp.Core distinct conçu pour .NETCF. (Il y a aussi un FSharp.Core séparé pour Silverlight.)
Brian

Quel est ce CTP dont vous parlez?
Jwosty
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.