Jestem zainteresowany lepszą nauką programowania funkcjonalnego. Aby to zrobić, wydaje się oczywiste, że powinienem zmusić się do użycia najczystszego możliwego funkcjonalnego języka programowania. Dlatego też mniej więcej tutaj proszę o uporządkowanie funkcjonalnych języków programowania zgodnie z ich czystością.
Wydaje mi się, że praktyczniej byłoby nauczyć się Lisp lub Clojure (lub Scheme, Scala itp.), Ale z powodu tego, co ostatnio słyszałem, Haskell byłby bardzo trudny do nauczenia kogoś, kto nauczałby zasad programowania funkcjonalnego. Nie jestem jeszcze tego pewien, więc pytam: który jest najczystszym funkcjonalnym językiem programowania? Kolejność byłaby świetna, gdyby kilku walczyło o wspaniały tytuł najczystszego funkcjonalnego języka programowania.
Odpowiedzi:
Nie ma skali do oceny stopnia czystości języków funkcjonalnych. Jeśli język dopuszcza skutki uboczne, jest nieczysty, w przeciwnym razie jest czysty. Zgodnie z tą definicją Haskell, Mercury, Clean itp. Są czystymi językami funkcjonalnymi; podczas gdy Scala, Clojure, F #, OCaml itp. są nieczyste.
EDYCJA: Może powinienem to sformułować jako „jeśli język nie dopuszcza skutków ubocznych bez powiadomienia systemu typów , jest czysty. W przeciwnym razie jest nieczysty”.
źródło
IO
monada). Po prostu kod powodujący skutki uboczne jest wyraźnie oznaczony jako taki. Nie sądzę, że w ogóle warto mówić o czystych / nieczystych językach (Haskell pozwala programować imperatywnie! Gasp!), Ale nadal może być przydatne mówienie o fragmentach kodu (funkcja, moduł, program, cokolwiek) jako czystych /zanieczyszczony.IO
monada jest czysta. Jest to biblioteka środowiska wykonawczego, która nie jest twoim kodem, ponieważ twojamain
funkcja jest w zasadzie ogromnym transformatorem stanu. (Coś jakmain :: World -> World
za kulisami)program = "some C code"
, a środowisko wykonawcze zajmuje się kodem C. :-)Ponieważ Twoim celem jest uczenie się, a nie pisanie programów per se, nie możesz uzyskać czystszego niż Rachunek Lambda .
Rachunek Lambda istniał już przed wynalezieniem komputerów. Pracowało nad tym kilku wykwalifikowanych logików, aby dowiedzieć się, jak wykonać odejmowanie (przez pewien czas uważano, że możliwe jest tylko dodawanie i mnożenie).
Nauczenie się, w jaki sposób booleany i liczby, i które
if
można wymyślić z pozornie nic, nie zwiększy ilości paliwa w twoim zbiorniku, ale sprawi, że twój zbiornik będzie znacznie większy.źródło
-1
.Zanieczyszczone języki tak naprawdę nie różnią się zasadniczo od bardziej znanych języków imperatywnych, zwłaszcza teraz, gdy skopiowano wiele sztuczek funkcjonalnych. Odmienny jest styl - sposób rozwiązywania problemów.
Niezależnie od tego, czy liczysz Haskella jako czysty, czy monadę IO jako nieczystość, styl Haskell jest ekstremalną formą tego stylu i warto się go nauczyć.
Monada IO Haskell wywodzi się z matematycznej teorii (oczywiście) monad. Jednak w przypadku programistów imperatywnych myślę, że powrót do monad ma większy sens.
Faza pierwsza - czysty język funkcjonalny może łatwo zwrócić dużą wartość ciągu. Ten duży ciąg może być kodem źródłowym programu imperatywnego, pochodzącego w sposób czysto funkcjonalny od niektórych parametrów określających wymagania. Następnie można zbudować kompilator „wyższego poziomu”, który uruchamia generator kodu, a następnie automatycznie podaje wygenerowany kod do kompilatora języka imperatywnego.
Faza druga - zamiast generować tekstowy kod źródłowy, generujesz silnie wpisane abstrakcyjne drzewo składniowe. Kompilator w języku imperatywnym jest wchłaniany do kompilatora „wyższego poziomu” i akceptuje AST bezpośrednio jako kod źródłowy. Jest to o wiele bliższe temu, co robi Haskell.
Jednak nadal jest to niezręczne. Na przykład masz dwa różne rodzaje funkcji - te oceniane podczas fazy generowania kodu i wykonywane podczas uruchamiania generowanego programu. To trochę jak rozróżnienie między funkcjami i szablonami w C ++.
Tak więc, dla fazy 3, uczyń obie te same - ta sama funkcja o tej samej składni może być częściowo oceniana podczas „generowania kodu”, lub w pełni oceniana, lub w ogóle nie oceniana. Ponadto należy odrzucić wszystkie zapętlone konstrukty AST na rzecz rekurencji. W rzeczywistości odrzuć ideę węzłów AST jako specjalnego rodzaju danych w ogóle - nie posiadaj węzłów AST o „wartości dosłownej”, tylko wartości itp.
To właśnie robi monada IO - operator bind jest sposobem komponowania „akcji” w celu tworzenia programów. To nic specjalnego - tylko funkcja. Wiele wyrażeń i funkcji można ocenić podczas „generowania kodu”, ale te, które zależą od efektów ubocznych I / O, muszą mieć ocenę opóźnioną do czasu wykonania - nie przez żadną specjalną regułę, ale jako naturalną konsekwencję zależności danych w wyrażenia.
Generalnie monady są po prostu uogólnieniem - mają ten sam interfejs, ale implementują operacje abstrakcyjne inaczej, więc zamiast ewaluować do opisu kodu imperatywnego, oceniają na coś innego. Posiadanie tego samego interfejsu oznacza, że istnieje kilka rzeczy, które możesz zrobić monadom, nie dbając o to, która monada, co okazuje się przydatne.
Ten opis bez wątpienia spowoduje eksplozję purystycznych głów, ale dla mnie wyjaśnia kilka prawdziwych powodów, dla których Haskell jest interesujący. Zaciera granicę między programowaniem a metaprogramowaniem i wykorzystuje narzędzia programowania funkcjonalnego do ponownego tworzenia imperatywnego programowania bez potrzeby specjalnej składni.
Krytykę, jaką mam szablony C ++, polega na tym, że są one rodzajem zepsutego czysto funkcjonalnego sublanguage w języku imperatywnym - aby ocenić tę samą podstawową funkcję w czasie kompilacji, a nie w czasie wykonywania, trzeba ją ponownie zaimplementować w zupełnie innym stylu kodowania. W Haskell, podczas gdy zanieczyszczenie musi być oznaczone jako takie w swoim typie, dokładnie ta sama funkcja może być oceniana zarówno w sensie metaprogramowania, jak i w trybie niemetaprogramowania w czasie wykonywania w tym samym programie - nie ma twardego wiersza między programowaniem a metaprogramowaniem.
To powiedziawszy, istnieją pewne rzeczy związane z metaprogramowaniem, których standardowy Haskell nie potrafi, głównie dlatego, że typy (i może kilka innych rzeczy) nie są pierwszorzędnymi wartościami. Istnieją jednak warianty językowe, które próbują rozwiązać ten problem.
Wiele rzeczy, które powiedziałem o Haskell, można zastosować w nieczystych językach funkcjonalnych - a czasem nawet w imperatywnych. Haskell jest inny, ponieważ nie masz innego wyjścia, jak przyjąć to podejście - w zasadzie zmusza Cię do nauki tego stylu pracy. Możesz „pisać C w ML”, ale nie możesz „pisać C w Haskell” - przynajmniej nie bez wiedzy o tym, co się dzieje pod maską.
źródło
Osobiście dzielę języki na trzy poziomy czystości funkcjonalnej:
Języki czysto funkcjonalne - tj. Te, które traktują cały program jako czystą funkcję i obsługują zmienność wyłącznie poprzez interakcję z środowiskiem wykonawczym - Haskell jest prawdopodobnie kanonicznym przykładem
Nieczyste języki funkcjonalne - tj. Te, które podkreślają funkcjonalny styl, ale pozwalają na efekty uboczne.Clojure jest wyraźnie w tej kategorii (pozwala mutować w kontrolowany sposób jako część swojego szkieletu STM), również OCaml lub F #
Języki z wieloma paradygmatami - nie są to przede wszystkim języki funkcjonalne, ale mogą obsługiwać styl funkcjonalny za pomocą funkcji pierwszej klasy itp. Scala jest tutaj dobrym przykładem, chciałbym również Common Lisp w tej kategorii, a można nawet dołączyć języki takie jak JavaScript .
W twojej sytuacji proponuję najpierw nauczyć się Haskell, a potem Clojure. Tak właśnie zrobiłem i działało to dla mnie bardzo dobrze! Haskell jest piękny i uczy najczystszych zasad funkcjonalnych, Clojure jest znacznie bardziej pragmatyczny i pomaga ci wiele zrobić, a jednocześnie jest bardzo funkcjonalny w sercu.
Tak naprawdę nie liczę trzeciej kategorii jako języków funkcjonalnych (chociaż po nauce Haskell i Clojure często korzystam z technik funkcjonalnych podczas ich używania!)
źródło
Jeśli czysty język funkcjonalny jest taki, że ma tylko czyste funkcje (procedury, które nie mają skutków ubocznych), to jest to trochę bezcelowe, ponieważ nie może odczytać danych wejściowych ani wyjściowych;)
Bo to jest naprawdę dla uczenia się, myślę, że izolacja nie jest koniecznie droga. Programowanie funkcjonalne jest paradygmatem. Ważne jest, aby zrozumieć, które paradygmaty są odpowiednie dla których problemów, a co ważniejsze, jak najlepiej je połączyć.
Poza tym, jeśli szukasz „czystości”, możesz rzucić okiem na Pure . Należy jednak pamiętać, że niezwykle łatwa funkcja wywoływania procedur C powoduje, że jest ona funkcjonalnie nieczysta (ale także bardzo wydajna).
źródło
Nie do końca poważna odpowiedź, ale Unlambda musi być konkurentem. Nie można uzyskać bardziej „czysto funkcjonalnego” niż kombinatory SKI.
źródło
Erlang, Haskell, Scheme, Scala, Clojure i F #
To pytanie prawdopodobnie najlepiej pomóc Ci w poszukiwaniu jak dobrze .
źródło
set!
(między innymi) ...