FP do symulacji i modelowania


12

Zaraz rozpocznę projekt symulacji / modelowania. Wiem już, że OOP służy do tego rodzaju projektów. Jednak badanie Haskella skłoniło mnie do rozważenia zastosowania paradygmatu FP do modelowania układu komponentów. Pozwól mi rozwinąć:

Załóżmy, że mam komponent typu A, charakteryzujący się zestawem danych (parametr taki jak temperatura lub ciśnienie, PDE i niektóre warunki brzegowe itp.) Oraz komponent typu B, charakteryzujący się innym zestawem danych (różnym lub ten sam parametr, różne PDE i warunki brzegowe). Załóżmy również, że funkcje / metody, które zostaną zastosowane do każdego komponentu, są takie same (na przykład metoda Galerkina). Zmienny stan obiektu zostałby zastosowany do parametrów niestałych.

Gdybym miał zastosować podejście OOP, stworzyłbym dwa obiekty, które enkapsulowałyby dane każdego typu, metody rozwiązywania PDE (dziedziczenie byłoby tu użyte do ponownego użycia kodu) i rozwiązanie PDE.

Z drugiej strony, gdybym miał zastosować podejście FP, każdy komponent byłby podzielony na części danych i funkcje, które działałyby na dane w celu uzyskania rozwiązania dla PDE. Parametry niestałe byłyby przekazywane jako funkcje czegoś innego (na przykład czas) lub wyrażane przez pewnego rodzaju zmienność (emulacja zmienności itp.) To podejście wydaje mi się prostsze, zakładając, że liniowe operacje na danych byłyby trywialne.

Podsumowując, czy wdrożenie podejścia FP byłoby faktycznie prostsze i łatwiejsze w zarządzaniu (dodaj inny typ komponentu lub nową metodę rozwiązania pde) w porównaniu do OOP?

Pochodzę z środowisk C ++ / Fortran, a ponadto nie jestem profesjonalnym programistą, więc popraw mnie na wszystko, co popełniłem źle.

Odpowiedzi:


7

Dobre pytanie, myślałem podobnie. Historycznie, paradygmat OO powstał z potrzeby symulacji komputerowej - zobacz historię Simuli - i pomimo wczesnych języków OO, takich jak Smalltalk , tworzonych przez ludzi, którzy wiedzieli, co robią (tj. Alan Kay), OO jest obecnie prawdopodobnie nadmiernie wykorzystywany i wprowadza o wiele za dużo przypadkowej złożoności .

Ogólnie rzecz biorąc, programy w stylu FP będą krótsze, łatwiejsze do testowania i łatwiejsze do modyfikacji niż programy OO. Jak to ujął Rob Harrop w swoim wystąpieniu: Czy przyszłość jest funkcjonalna? , nigdy nie możesz być prostszy niż funkcje i dane; oba komponują się nieskończenie, aby stworzyć wszelkie potrzebne abstrakcje. Tak więc jednym ze sposobów udzielenia odpowiedzi na pytanie (czy po prostu go odtwarzam? :) jest pytanie, jaka jest funkcja najwyższego poziomu i jak wyglądają dane wejściowe najwyższego poziomu -> dane wyjściowe? Następnie możesz zacząć rozkładać funkcje „alfa” i typy danych na następną warstwę abstrakcji i powtarzać w razie potrzeby.

Inną perspektywą (nie całkiem odpowiedzi) na twoje pytanie jest spojrzenie na ten wątek (wyłączenie odpowiedzialności, zacząłem go) na StackOverflow, niektóre odpowiedzi są bardzo interesujące: /programming/3431654/how-does- funkcjonalne programowanie-zastosowanie-do symulacji

Moje własne zdanie w tym momencie jest takie, chyba że modelujesz sytuację, w której naprawdę istnieją dyskretne obiekty, które oddziałują tylko w określony sposób (np. Model sieci komputerowej) - a zatem odwzorowują bezpośrednio możliwości czystego komunikatu przelotny paradygmat język OO - łatwiej jest przejść na FP. Zauważ, że nawet w społeczności programistów gier - gdzie symulacje są bardzo rozpowszechnione, a wymagania dotyczące wydajności są najważniejsze - doświadczeni programiści odchodzą od paradygmatu OO i / lub używają większej liczby FP, np. Patrz ta dyskusja HN lub komentarze Johna Carmacka na temat FP


Dobrze wiedzieć, że nie tylko wątpię w OOP w symulacji i dziękuję za odpowiedź na moje pytanie! Przeczytałem komentarze Johna Carmacka dotyczące FP i pomyślałem o wdrożeniu niektórych aspektów FP w C ++ (kopiowanie obiektów lub zebranie danych wejściowych i przekazanie ich do funkcji), ale z drugiej strony nie wiem, czy powinienem rozpocząć projekt z C ++ zamiast języka FP, takiego jak Haskell, ponieważ aspekty FP są wbudowane i wyrażasz zmienność tylko wtedy, gdy jest to potrzebne. Czy nadal korzystałeś z Clojure lub FP ogólnie biorąc pod uwagę, że miałeś podobny problem / pytanie?
heaptobesquare

@heaptobesquare - Tak, stale rozwijam swoje Clojure-fu w celu pisania w nim symulacji. Nic jeszcze nie jest gotowe do pokazania, ale nie widzę żadnych przeszkód, a projekt Clojure jest pięknie pragmatyczny, np. Możesz użyć transjentów / mutacji w razie potrzeby, a jego agenci są dobrze dostosowani do aspektów asynchronicznych. W pewnym momencie (bez obietnic kiedy) napiszę artykuł na ten temat ...
limist

Rzuciłem okiem na Clojure, ale nie mogę powiedzieć, że lubię wyrażenia S. Wiem, że jest to praktyczne (kod Lisp to dane), ale czy łatwo się przyzwyczaić?
heaptobesquare

@heaptobesquare - składnia s-wyrażeń / Lisp jest bardzo łatwa do przyzwyczajenia; najpierw wybierz dobrego edytora (Emacs lub vim, mój głos dotyczy Emacsa, patrz dev.clojure.org/display/doc/Getting+Started+with+Emacs ), który ma tryb Clojure, zdobądź dobrą książkę (np. Programowanie Clojure ) i zacznij hakować. Po najwyżej kilku tygodniach składnia zniknie w tle, tak jak powinna - jest tak idealnie spójna, że ​​będziesz myślał o niej wykładniczo rzadziej i zwolnisz cykle mentalne na ważniejsze rzeczy. :)
limist

Zdecydowanie wtedy spróbuję. W końcu homoikoniczność Lispa jest interesująca.
heaptobesquare

2

IMHO na prawie każde zadanie o rozsądnej złożoności nie można obiektywnie odpowiedzieć na pytanie „styl FP lub styl OOP lepszy wybór”. Zazwyczaj w takiej sytuacji pytaniem nie jest „ani FP, ani OOP”, ale jak połączyć najlepsze części obu paradygmatów w celu rozwiązania problemu.

Problem, który naszkicowałeś powyżej, wydaje się bardzo matematyczny, i przypuszczam, że będziesz potrzebować kilku operacji na macierzach. OOP jest bardzo dobry do modelowania abstrakcyjnych typów danych, a rachunek macierzowy można łatwo zaimplementować jako „obiekty macierzy” za pomocą operacji na macierzach. Zaimplementowanie tego w sposób, w którym wszystkie operacje na macierzach są częścią klasy macierzy, pomaga utrzymać razem rzeczy, które do siebie należą, dzięki czemu zachowana jest dobra ogólna struktura.

Z drugiej strony, PDE są równaniami funkcji, a rozwiązaniem może być znowu funkcja. Zatem zastosowanie funkcjonalnego podejścia do tego rodzaju „komponentów” może wydawać się tutaj naturalne. Funkcje te mogą mieć parametry macierzy, pokazujące jeden przykład połączenia OOP i FP. Innym przykładem może być implementacja klasy macierzy, która wykorzystuje narzędzia funkcjonalne do mapowania określonej operacji na każdy element macierzy. Także tutaj nie jest to „OOP kontra FP”, ale „OOP w połączeniu z FP”, który przynosi najlepsze wyniki.


Dziękuję za Twoją odpowiedź! Tak więc, gdybym używał C ++, enkapsulowałbym tylko dane (tj. Parametry, warunki brzegowe i PDE w postaci macierzy) komponentu do obiektu i definiowałby funkcje (nawet te wyższego rzędu, w przypadku parametr jest funkcją czegoś innego), poza zakresem obiektu, który działałby na danych obiektu, byłby wydajny?
heaptobesquare

@heaptobesquare: szczerze mówiąc, nie mogę powiedzieć, czy będzie to skuteczne w twoim przypadku. Spróbuj, myśl na wielką skalę, zacznij od małej. Rozpocznij programowanie „kodu śledzenia ” ( artima.com/intv/tracer.html ), aby dowiedzieć się, co działa najlepiej, a co nie. A jeśli dojdziesz do sytuacji, w której zauważysz, że coś nie działa poprawnie, refaktoryzuj.
Doc Brown,

Haskell ma bibliotekę Hmatrix, która jest powiązaniami dla bibliotek BLAS / LAPACK, i bardzo ładną składnię, którą wybrałbym osobiście.
Paul

@paul: Dzięki, na pewno się temu przyjrzę! Czy biblioteki Haskell są ogólnie spójne i bogate w treści? Wiki tak mówi, ale czy to fakt?
heaptobesquare

@heaptobesquare: Jedyną biblioteką Haskell, z której korzystałem w jakimkolwiek stopniu, jest Parsec (użyłem jej do napisania asemblera), ale uwielbiałem jej używać. Przeprowadziłem tylko eksplorację GHCI Hmatrix i powiązań Haskell OpenGL, ale wydają się całkiem fajne. Hmatrix wydaje się być tak zwięzły jak MATLAB (którego dość często używałem) - który został stworzony specjalnie do tego rodzaju rzeczy. Z mojego ograniczonego doświadczenia wynika, że ​​biblioteki są spójne - to dlatego, że Haskell jest zbudowany na niewielkiej liczbie prostych bloków konstrukcyjnych - i są również bogate, ponieważ Haskellery nie lubią robić rzeczy przyziemnych :)
Paul
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.