Funkcjonalne programowanie reaktywne - Functional reactive programming

Funkcjonalne programowanie reaktywne ( FRP ) to paradygmat programowania do programowania reaktywnego ( programowania asynchronicznego przepływu danych ) z wykorzystaniem bloków konstrukcyjnych programowania funkcjonalnego (np. map , reduction , filter ). FRP został wykorzystany do programowania graficznych interfejsów użytkownika (GUI), robotyki , gier i muzyki, mając na celu uproszczenie tych problemów poprzez jawne modelowanie czasu.

Formulacje FRP

Oryginalne sformułowanie funkcjonalnego programowania reaktywnego można znaleźć w artykule ICFP 97 Functional Reactive Animation autorstwa Conala Elliotta i Paula Hudaka .

FRP przybierał wiele form od czasu jego wprowadzenia w 1997 roku. Jedną z osi różnorodności jest semantyka dyskretna i ciągła. Kolejną osią jest to, jak systemy FRP mogą być dynamicznie zmieniane.

Ciągły

Najwcześniejsze sformułowanie FRP wykorzystywało semantykę ciągłą, mającą na celu wyabstrahowanie wielu szczegółów operacyjnych, które nie są ważne dla znaczenia programu. Kluczowe właściwości tego preparatu to:

  • Wartości modelowania, które zmieniają się w ciągłym czasie, zwane „zachowaniami”, a później „sygnałami”.
  • Modelowanie „ zdarzeń ”, które występują w dyskretnych punktach w czasie.
  • System można zmieniać w odpowiedzi na zdarzenia, ogólnie określane jako „przełączanie”.
  • Oddzielenie szczegółów oceny, takich jak częstotliwość próbkowania, od modelu reaktywnego.

Ten semantyczny model FRP w językach wolnych od skutków ubocznych jest zwykle pod względem funkcji ciągłych i zazwyczaj w czasie.

Oddzielny

Formuły takie jak FRP sterowane zdarzeniami i wersje Elm przed 0.17 wymagają, aby aktualizacje były dyskretne i sterowane zdarzeniami. Te sformułowania naciskały na praktyczne FRP, koncentrując się na semantyce, która ma prosty interfejs API, który można skutecznie zaimplementować w środowisku takim jak robotyka lub przeglądarka internetowa.

W tych sformułowaniach często idee zachowań i zdarzeń są łączone w sygnały, które zawsze mają aktualną wartość, ale zmieniają się dyskretnie.

Interaktywny FRP

Zwrócono uwagę, że zwykły model FRP, od wejść do wyjść, jest słabo dostosowany do programów interaktywnych. Brak możliwości „uruchamiania” programów w ramach mapowania wejść na wyjścia może oznaczać konieczność zastosowania jednego z następujących rozwiązań:

  • Utwórz strukturę danych działań, które pojawiają się jako dane wyjściowe. Akcje muszą być wykonywane przez zewnętrznego tłumacza lub środowisko. Dziedziczy to wszystkie trudności oryginalnego systemu I/O strumienia Haskella.
  • Użyj Arrowized FRP i osadzaj strzały, które są zdolne do wykonywania akcji. Akcje mogą również posiadać tożsamości, co pozwala im na przykład na utrzymywanie oddzielnych magazynów mutowalnych. Jest to podejście przyjęte przez bibliotekę Fudgets i, bardziej ogólnie, Monadic Stream Functions.
  • Nowatorskim podejściem jest umożliwienie wykonywania akcji teraz (w monadzie IO), ale odłożenie otrzymania ich wyników na później. Wykorzystuje to interakcję między monadami Event i IO i jest kompatybilne z bardziej zorientowanym na ekspresję FRP:
planNow :: Event (IO a) -> IO (Event a)

Problemy wdrożeniowe

Istnieją dwa rodzaje systemów FRP, oparte na push i pull-based. Systemy oparte na wypychaniu przyjmują zdarzenia i przepychają je przez sieć sygnałową, aby osiągnąć wynik. Systemy oparte na ściąganiu czekają na żądanie wyniku i pracują wstecz przez sieć, aby pobrać żądaną wartość.

Niektóre systemy FRP, takie jak Yampa, wykorzystują próbkowanie, w którym próbki są pobierane przez sieć sygnałową. Takie podejście ma wadę: sieć musi czekać do czasu trwania jednego kroku obliczeniowego, aby dowiedzieć się o zmianach danych wejściowych. Próbkowanie jest przykładem FRP opartego na ściąganiu.

Biblioteki Reactive i Etage w Hackage wprowadziły podejście zwane push-pull FRP. W tym podejściu tylko wtedy, gdy wymagane jest następne zdarzenie w czysto zdefiniowanym strumieniu (takim jak lista stałych zdarzeń z czasami), to zdarzenie jest konstruowane. Te czysto zdefiniowane strumienie działają jak leniwe listy w Haskell. To jest połowa oparta na pociągnięciu. Połówka oparta na wypychaniu jest używana, gdy wprowadzane są zdarzenia zewnętrzne w stosunku do systemu. Zdarzenia zewnętrzne są przekazywane do konsumentów, aby mogli dowiedzieć się o zdarzeniu natychmiast po jego wydaniu.

Realizacje

  • Yampa to strzałkowata, wydajna, czysta implementacja Haskella z obsługą SDL, SDL2, OpenGL i HTML DOM.
  • Język programowania Elm używany do obsługi FRP, ale od tego czasu zastąpił go innym wzorcem
  • reflex to wydajna implementacja push/pull FRP w Haskell z hostami dla przeglądarki / DOM , SDL i Gloss.
  • Reactive-banana to docelowa implementacja push FRP niezależna od celu w Haskell.
  • netwire i zmienne są oznaczone strzałkami, ściągają implementacje FRP w Haskell.
  • Flapjax to implementacja FRP behawioralno-zdarzeniowa w JavaScript .
  • React to moduł OCaml do funkcjonalnego programowania reaktywnego.
  • Sodium to implementacja push FRP niezależna od określonej struktury interfejsu użytkownika dla kilku języków programowania, takich jak Java, TypeScript i C#.
  • ReactiveX , spopularyzowany przez implementację JavaScript rxjs , to wszechstronny, wieloplatformowy paradygmat implementacji funkcjonalnego programowania reaktywnego poprzez traktowanie danych jako strumieni obserwowalnych.
  • Dunai to szybka implementacja w Haskell wykorzystująca Monadic Stream Functions, która obsługuje klasyczne i Arrowized FRP.
  • ObservableComputations , wieloplatformowa implementacja platformy .NET.
  • Stella to reaktywny język programowania oparty na aktorach, który demonstruje model „aktorów” i „reaktorów”, który ma na celu uniknięcie problemów łączenia kodu imperatywnego z kodem reaktywnym (poprzez rozdzielenie ich na aktorów i reaktory). Aktory nadają się do stosowania w rozproszonych systemach reaktywnych.

Zobacz też

Bibliografia

Linki zewnętrzne