W jakich obszarach użycie F # może być bardziej odpowiednie niż C #? [Zamknięte]

210

W ciągu ostatnich kilku lat F # ewoluowało w jednym z w pełni obsługiwanych języków Microsoftu, wykorzystując wiele pomysłów inkubowanych w OCaml, ML i Haskell.

W ciągu ostatnich kilku lat C # rozszerzył swoje funkcje ogólnego przeznaczenia, wprowadzając coraz bardziej funkcjonalne funkcje językowe: LINQ (rozumienie listy), Lambdas, Zamknięcia, Anonimowi Delegaci i więcej ...

Biorąc pod uwagę przyjęcie przez C # tych funkcji funkcjonalnych i taksonomię F # jako nieczystego języka funkcjonalnego (umożliwia TYM dostęp do bibliotek frameworka lub zmianę stanu współdzielonego po wywołaniu funkcji, jeśli chcesz), istnieje silne podobieństwo między tymi dwoma językami, chociaż każdy ma swoją własny biegun przeciwny główny nacisk.

Interesują mnie wszelkie udane modele wykorzystujące te dwa języki w produkcyjnych programach poliglotycznych, a także obszary w oprogramowaniu produkcyjnym (aplikacje internetowe, aplikacje klienckie, aplikacje serwerowe), które napisałeś w języku F # w ubiegłym roku lub mniej więcej tak, jak wcześniej napisane w C #.

Peter McG
źródło

Odpowiedzi:

258

Napisałem wniosek o zrównoważenie krajowego harmonogramu wytwarzania energii dla portfela elektrowni do pozycji handlowej dla firmy energetycznej. Składniki klienta i serwera były w języku C #, ale silnik obliczeniowy został napisany w języku F #.

Zastosowanie F # w celu rozwiązania problemu złożoności w sercu tej aplikacji wyraźnie pokazuje, że język oprogramowania firmowego jest najsłabszy, a mianowicie złożoną algorytmicznie analizę dużych zbiorów danych. Moje doświadczenie było bardzo pozytywne. W szczególności:

Jednostki miary Przemysł, w którym pracuję, jest zaśmiecony jednostkami. Wprowadzone przeze mnie równania (często o charakterze geometrycznym) dotyczyły jednostek czasu, mocy i energii. Sprawdzanie poprawności jednostek wejściowych i wyjściowych funkcji w systemie typów to ogromna oszczędność czasu, zarówno pod względem testowania, jak i odczytu / rozumienia kodu. Eliminuje całą klasę błędów, na które podatne były poprzednie systemy.

Programowanie eksploracyjne Praca z plikami skryptowymi i REPL (F # Interactive) pozwoliła mi lepiej zbadać przestrzeń rozwiązania przed przystąpieniem do implementacji niż bardziej tradycyjna pętla edycji / kompilacji / uruchomienia / testu. Jest to bardzo naturalny sposób dla programistów, aby budowali swoje zrozumienie problemu i napięć projektowych w grze.

Testowanie jednostkowe Kod napisany przy użyciu funkcji niepowodujących efektów ubocznych i niezmiennych struktur danych to przyjemność testować. Nie ma skomplikowanych interakcji zależnych od czasu, które mogłyby spieprzyć sprawę, lub dużych zestawów zależności, które można wyśmiewać.

Interoperacja Zdefiniowałem interfejs do silnika obliczeniowego w C # i wdrożyłem obliczenia w F #. Silnik obliczeniowy można następnie wprowadzić do dowolnego modułu C #, który musiał go używać bez żadnych obaw o interoperacyjność. Bezszwowy. Programista C # nigdy nie musi wiedzieć.

Redukcja kodu Wiele danych wprowadzonych do silnika obliczeniowego miało postać wektorów i macierzy. Funkcje wyższego rzędu jedzą je na śniadanie z minimalnym zamieszaniem, minimalnym kodem. Piękny.

Brak błędów Programowanie funkcjonalne może wydawać się dziwne. Mogę pracować nad algorytmem, ciężko próbując zdobyć kod, aby przekazać moduł sprawdzania typu, ale gdy moduł sprawdzania typu jest zadowolony, to działa. Jest prawie dwójkowy, albo się nie skompiluje, albo jest poprawny. Dziwne błędy przypadku krawędzi są minimalizowane, funkcje rekurencji i wyższego rzędu usuwają wiele kodu księgowego, który wprowadza błędy przypadku krawędzi.

Równoległość Czystość funkcjonalna wynikowej implementacji sprawia, że ​​jest ona gotowa do wykorzystania nieodłącznej równoległości w przetwarzaniu wektorów danych. Być może właśnie tam pójdę teraz, kiedy .NET 4 jest dostępny.

kuzynów-simonów
źródło
18
+1 za wyjaśnienie, dlaczego F # jest bardzo odpowiedni dla silników z trzaskiem liczb. Kolejny (wirtualny) +1 za podanie jednostek miary. Ta część języka zasługuje na częstsze wymienianie.
cfern
5
Świetna odpowiedź, trafna, współczesna i zarysowująca przydatność F # do radzenia sobie ze złożonością, wiele się nauczyłem z czytania, dzięki
Peter McG
Świetna odpowiedź Simon i, jak wspomniał Don ostatniej nocy, zacytowany w swoich ostatnich slajdach. Czas dodać link „dodaj do koszyka”?
Chris Ballard
1
cześć, czy możesz powiedzieć nam więcej o swojej architekturze aplikacji?
Nikos,
76

Podczas stażu w Microsoft Research pracowałem nad niektórymi częściami Visual Studio IntelliSense dla F # (które jest napisane w F #). Miałem już pewne doświadczenie z IntelliSense z wcześniejszych projektów w języku C #, więc myślę, że mogę je porównać.

  • Rozszerzalność programu Visual Studio jest nadal oparta na modelu COM, więc musisz radzić sobie z obiektami, które nie są bardzo ładnymi obiektami .NET (i zdecydowanie nie działają), ale nie uważam, że istnieje jakaś znacząca różnica między C # i F # (działa płynnie z F #)

  • Struktury danych używane do reprezentowania kodu programu w języku F # są w większości dyskryminowanymi związkami (które nie są obsługiwane w języku C # w żaden rozsądny sposób), co stanowi ogromną różnicę dla tego rodzaju aplikacji (gdzie trzeba przetwarzać struktury drzewa, takie jak kod programu ). Zróżnicowane związki i dopasowanie wzorców pozwala lepiej ustrukturyzować kod (zachowaj powiązaną funkcjonalność w jednym miejscu, zamiast mieć to wszystko w metodach wirtualnych)

Wcześniej pracowałem również nad dostawcą CodeDOM dla F # (również napisanym w F #). Właściwie najpierw przeprowadzałem eksperymenty w C #, ale potem przekonwertowałem kod na F #.

  • Dostawca CodeDOM musi przejść przez pewną strukturę reprezentowaną za pomocą obiektów .NET, więc nie ma wiele miejsca na wymyślanie własnych reprezentacji danych (w tym obszarze F # może oferować miłe korzyści).

  • Było jednak wiele małych funkcji F #, które ułatwiły zadanie. Ponieważ musisz utworzyć ciąg, zdefiniowałem niestandardowe operatory do budowania ciągów (używającStringBuilder ) i zaimplementowałem kod, używając ich i funkcji wyższego rzędu (np. Do sformatowania listy obiektów oddzielonych za pomocą określonego ciągu itp.), Co usunęło wiele powtórzenia (i żmudne foreachpętle).

Są to dwa stosunkowo konkretne przykłady, ale oba są związane z pracą z reprezentacjami programów lub wyrażeń, lub bardziej ogólnie, złożonymi, podobnymi do drzewa strukturami danych. Myślę, że w tym obszarze F # jest zdecydowanie dobrym wyborem (niezależnie od funkcji w C #).

Tomas Petricek
źródło
6
Bardzo ciekawe, więcej dowodów na to, że absorpcja F # w Microsoft jest z pewnością wysoka, co za świetny staż musiał być!
Peter McG
43

Dostarczyliśmy pierwszy na świecie produkt komercyjny napisany w języku F # ( F # dla wizualizacji ) i drugi ( F # dla liczb ), a także pierwszą literaturę komercyjną na temat F # ( The F # .NET Journal ) oraz napisaliśmy i opublikowaliśmy jedyną książkę o aktualnej wersji of F # ( Visual F # 2010 for Technical Computing ).

Wysyłaliśmy produkty według podobnych linii napisanych w C # (np Ten ), ale mieliśmy również silne doświadczenie w komercyjnym wykorzystaniu OCaml. Byliśmy entuzjastycznie nastawieni do F #, kiedy jeszcze był to prototyp badawczy w 2006 roku, ponieważ zdaliśmy sobie sprawę z potencjału posiadania przyzwoitego nowoczesnego języka podobnego do OCaml na przemysłowej platformie .NET i w związku z tym staraliśmy się go wyprodukować. Rezultat okazał się niesamowitym sukcesem, a F # znacznie przekroczył nasze wzniosłe oczekiwania.

Dla nas F # ma wiele różnych zalet i używamy go do wielu różnych zastosowań. W produkcji mamy setki tysięcy linii kodu F #. Teraz używamy F # dla wszystkich naszych aplikacji LOB: nasze transakcje kartami kredytowymi są przetwarzane przy użyciu kodu F #, nasze powiadomienia o produktach są wysyłane przy użyciu kodu F #, nasze subskrypcje są obsługiwane przy użyciu kodu F #, nasze konta są realizowane przy użyciu kodu F # i tak dalej. Być może główną cechą językową, która przynosi dywidendy, jest dopasowanie wzorca. Użyliśmy nawet F # do kolorowania składni podkreślenia naszej najnowszej książki ...

Nasza biblioteka wizualizacji jest dużym sprzedawcą, a jej funkcjonalność koncentruje się na interaktywnym F # działającym w Visual Studio. Nasza biblioteka powiększa to o możliwość tworzenia interaktywnych wizualizacji 2D i 3D przy minimalnym wysiłku (np. Po prostuPlot([Function sin], (-6., 6.))wykreślić falę sinusoidalną). W szczególności wszystkie problemy z wątkami są całkowicie zautomatyzowane, więc użytkownicy nie muszą martwić się wątkami interfejsu użytkownika i wysyłką. Pierwszorzędne funkcje i lenistwo były niezwykle cenne podczas pisania tej części biblioteki, a typy danych algebraicznych były szeroko stosowane gdzie indziej. Przewidywalna wydajność również okazała się tu cenna, gdy nasi klienci napotkali błędy wydajności w testach trafień WPF i byli w stanie z łatwością zaimplementować odpowiedni kod w F # w celu zwiększenia wydajności o 10 000 ×. Ze względu na swobodny charakter GUI tego produktu, projektant GUI i C # nie byłyby korzystne.

Wiele naszych prac dotyczy metod numerycznych, w tym zarówno naszych komercyjnych bibliotek, jak i książek. F # jest znacznie silniejszy w tym obszarze niż C #, ponieważ oferuje abstrakcje wysokiego poziomu (np. Funkcje wyższego rzędu) przy minimalnych karach wydajności. Naszym najbardziej przekonującym rezultatem w tym kontekście było stworzenie prostej, ale uogólnionej implementacji dekompozycji QR z algebry liniowej, która była 20 razy krótsza niż kod Fortran z referencyjnej implementacji LAPACK, nawet 3 razy szybciej niż dostrojony przez dostawcę Intel Math Biblioteka jądra i bardziej ogólna, ponieważ nasz kod może obsługiwać macierze dowolnego typu, nawet macierze symboliczne!

Obecnie opracowujemy komponenty WPF / Silverlight w kombinacji F # (dla wnętrzności) i C # (dla shim), budując aplikacje WPF, które działają jako interaktywne podręczniki dla naszych produktów programowych i piszę nową książkę, Multicore F #, która będzie ostatecznym przewodnikiem po równoległym programowaniu w pamięci współużytkowanej w .NET.

Jon Harrop
źródło
Czy jesteś tym samym Jonem Harropem, który napisał „F # for Scientists”?
Andre Artus,
7
Tak. Napisałem F # dla naukowców 5 lat temu.
Jon Harrop,
Czy masz jakieś odniesienia do kodu rozkładu QR w F #, o którym wspomniałeś w przedostatnim akapicie? Dzięki.
Samik R
@SamikR: Nie, przepraszam. To jest kod handlowy. Łatwo było jednak pisać.
Jon Harrop,
@Jon jakieś słowo na Multicore F #?
profesor bigglesworth,
25

Przez ostatnie 6 miesięcy pracowałem nad warstwą emulacji Vima dla Visual Studio 2010. Jest to darmowy produkt ze wszystkimi źródłami, które są dostępne bezpłatnie na github

Projekt jest podzielony na 3 biblioteki DLL reprezentujące odrębną warstwę. Każda warstwa ma odpowiednią bibliotekę dll testu jednostkowego.

  1. Silnik Vim: F #
  2. Warstwa WPF do ozdób i integracji z edytorem: C #
  3. Warstwa integracji Visual Studio: C #

To pierwszy duży projekt, jaki kiedykolwiek zrealizowałem z F # i muszę powiedzieć, że kocham ten język. Pod wieloma względami użyłem tego projektu jako metody uczenia się języka F # (i ta krzywa uczenia się jest bardzo widoczna, jeśli spojrzysz na historię projektu).

Najbardziej zdumiewające w F # jest to, jak zwięzły jest język. Silnik Vima stanowi większość logiki, ale stanowi jedynie 30% ogólnej podstawy kodu.

JaredPar
źródło
19
Edytor ... język funkcjonalny ... emulacja vi ... na nowo wymyśliłeś emacsa. NOOOOOOOOOOOOOOOOOOOOOOO!
Ben Voigt
2
Tyle że jest „Certyfikowany w 100% bez nawiasów” :)
Pavel Minaev
@Pavel, z wyjątkiem oczywiście krotek i wywołań metod .net
JaredPar
26
Dwie ważne rzeczy tutaj. Przede wszystkim krotki nie potrzebują ()w F # - to ,operator je tworzy, więc let x = 1,2jest to poprawna krotka już bez żadnych parenów. Po drugie, każdą parę parens w F # można zastąpić parami begin.. end(jest to dziedziczone z ML) - więc na przykład "foo".IndexOf begin 'a', 1 endjest to prawidłowe wywołanie metody .NET. Więc jeśli kiedykolwiek chciałeś być wolny od parens, F # jest jednym językiem, który pozwala ci to zrobić :)
Pavel Minaev
Zabawny komentarz Pavel! Nie wiedziałem tego. Myślę, że w niektórych przypadkach z dużych bloków grupujących, może faktycznie wolę begin.. end. RÓWNIEŻ: ZASADY VsVim!
Dan Fitch
13

Wiele testów jednostkowych składników F # Visual Studio jest napisanych w języku F #. Działają poza VS, kpiąc z różnych bitów Visual Studio. Umiejętność rozpoznawania anonimowych obiektów implementujących interfejsy jest przydatna zamiast fałszywego frameworka / narzędzia. Mogę po prostu pisać

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 )

kiedy muszę instancję np IVsOutputWindowPaneprzejść do innego składnika, który zostanie ostatecznie dzwoniącej OutputStringi Clear, a następnie skontrolować string list refobiekt na końcu testu, aby zobaczyć czy oczekiwany wynik został napisany.

Brian
źródło
Ciekawe, więcej dowodów na to, że absorpcja F # w Microsoft jest z pewnością wysoka. Nie wiedziałem, że możesz tworzyć anonimowe obiekty, które implementują interfejsy w F #
Peter McG
9

Napisaliśmy niestandardowy język silnika reguł za pomocą implementacji Lex-Yacc w F #

EDYCJA, aby dołączyć odpowiedź na komentarz

W C # nie było implementacji lex / yacc. (o ile nam wiadomo, a F # jeden był)

Byłoby to możliwe, ale wręcz samemu zbudować parsowanie.

W tym temacie przedstawiono kilka innych sugestii, takich jak biblioteki zewnętrzne, ale nasz główny architekt stara się posługiwać językami funkcjonalnymi, więc wybór użycia F # był oczywisty.

johnc
źródło
+1 Czy wcześniej napisałeś to w C #, czy z jakiegoś powodu było to nieodpowiednie lub wolniejsze?
Peter McG
@Peter McGrattan Przynajmniej w momencie pisania (oprogramowania) nie było implementacji lex / yacc w języku C #. Byłoby to możliwe, ale wręcz samemu zbudować parsowanie. stackoverflow.com/questions/540593/lex-yacc-for-c pokazuje kilka innych sugestii, ale nasz główny architekt jest starą ręką w językach funkcjonalnych, więc wybór użycia F # był oczywisty
John
jeśli myślałeś, że nie ma lex / yacc dla C #, obawiam się, że po prostu nie szukałeś na to wystarczająco dużo (jest jeden starszy niż F #), który powiedział, że jeśli potrzebujesz lex / yacc F # jest moim zdaniem znacznie bardziej odpowiedni młot dla tego gwoździa niż c #
Rune FS
Sam używałem F # z fslex / fxyacc, choć nie w projekcie „produkcyjnym” (zresztą i tak jeszcze nie wydanym) - wyróżnianie składni MSIL i rozszerzenie uzupełniania kodu dla VS. Główną zaletą używania F # jest to, że dostajesz ADT, które są bardzo wygodne do reprezentowania parsowania drzew. Ponadto użycie zamków błyskawicznych ( en.wikipedia.org/wiki/Zipper_(data_structure) ) ułatwia wykonywanie przyrostowego leksykowania - a zamki, ponieważ są funkcjonalne, łatwiej jest zwięźle manipulować w języku F #.
Pavel Minaev,
7

Obecnie pracuję nad kompilacją dla języka programowania. Kompilator jest napisany całkowicie w języku F #. Kompilator (oprócz kompilacji lex i parsera z lex / yacc) jest w zasadzie budowany jako duża transformacja złożonej struktury drzewiastej.

Jak zauważają inni, dyskryminacja związków i dopasowywanie wzorców sprawia, że ​​praca z tego rodzaju strukturą danych jest o wiele łatwiejsza niż zrzucanie kodu metodami wirtualnymi „wszędzie”

Nie wykonałem żadnej pracy w języku F #, zanim zacząłem pracować nad kompilatorem (miałem jednak kompilatory typu buld w innym wariancie OCaml o nazwie MoscowML) i tak jak Jared stwierdza z kodu, które części zrobiłem najpierw, ale ogólnie uważałem, że F # jest łatwe nauczenie się, jak ponownie wejść do trybu umysłu FP po kodowaniu głównie OO przez dekadę, zajmie trochę więcej czasu.

pracując z drzewami na bok, uważam, że zdolność do pisania deklaratywnego kodu jest główną zaletą FP (w tym F #) posiadającego kod opisujący algorytm, który próbuję zaimplementować w przeciwieństwie do C # opisującego, jak zaimplementowałem algortihm, jest ogromną zaletą.

Rune FS
źródło
6

Nie osobiste doświadczenia, ale możesz posłuchać odcinka DNR (myślę, że to ten ), w którym rozmawiają z Microsoftem folk na temat F #. Napisali większość systemu punktacji Xbox Live, który nie był trywialny, używając F #. System skalował się masowo na setkach maszyn i byli z niego bardzo zadowoleni.

Igor Zevaka
źródło
5

Nie wiem, czy jest w produkcji, ale AI dla „The Path of Go” zostało napisane w F #:

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

The Path of Go: Microsoft Research Game na konsolę Xbox 360

To demo pokazuje grę Xbox 360, opartą na grze Go, wyprodukowaną wewnętrznie w Microsoft Research Cambridge. Go to jedna z najbardziej znanych gier planszowych w Azji Wschodniej, która powstała w Chinach 4000 lat temu. Za zwodniczą prostotą gry kryje się wielka złożoność. Nauka zajmuje tylko kilka minut, ale opanowanie zajmuje całe życie. Chociaż komputery przewyższyły umiejętności ludzkie w szachach, wdrożenie konkurencyjnej sztucznej inteligencji dla Go pozostaje wyzwaniem badawczym. Gra oparta jest na trzech technologiach opracowanych w Microsoft Research Cambridge: sztucznej inteligencji zdolnej do grania w Go, języku F # i TrueSkill ™ w celu dopasowania do graczy online. AI jest zaimplementowane w F # i spełnia wyzwanie wydajnego działania w kompaktowym środowisku .net na Xbox 360. Ta gra umieszcza Cię w wielu oszałamiających wizualnie scenach 3D. Został w pełni opracowany w kodzie zarządzanym przy użyciu środowiska XNA.

(Ktoś inny wspomniał już o „TrueSkill”).

Brian
źródło
Fascynujące: F # działa na kompaktowym frameworku na XBox. Czy FSharp.Core.dll wraz z FSharp.Core.optdata FSharp.Core.sigdata nie odwołuje się do zestawów innych niż CF?
Peter McG
1
CTP jest dostarczany z osobnym FSharp.Core, który jest budowany dla .NETCF. (Istnieje również osobna FSharp.Core dla Silverlight.)
Brian
O czym jest ten CTP, o którym mówisz?
Jwosty