haskell - rxjava - ¿Cuál es el estado de las implementaciones actuales de Programación Reactiva Funcional?
programacion reactiva ventajas y desventajas (3)
Aunque ya hay algunas buenas respuestas, intentaré responder a sus preguntas específicas.
reactivo no es utilizable para proyectos serios, debido a problemas de fuga de tiempo. (ver # 3). La biblioteca actual con el diseño más similar es plátano reactivo, que se desarrolló con reactiva como inspiración, y en discusión con Conal Elliott.
Aunque el propio Haskell no es apropiado para aplicaciones duras en tiempo real, en algunos casos es posible utilizar Haskell para aplicaciones en tiempo real. No estoy familiarizado con la investigación actual, pero no creo que este sea un problema insalvable. Sospecho que sistemas como Yampa, o sistemas de generación de código como Atom, son posiblemente el mejor enfoque para resolver esto.
Una "fuga de tiempo" es un problema específico de FRP conmutable. La fuga ocurre cuando un sistema no puede liberar objetos viejos porque puede necesitarlos si ocurriera un cambio en algún momento en el futuro. Además de una pérdida de memoria (que puede ser bastante grave), otra consecuencia es que, cuando se produce el cambio, el sistema debe pausar mientras se atraviesa la cadena de objetos antiguos para generar el estado actual.
Las bibliotecas frp no conmutables como Yampa y las versiones anteriores de plátano reactivo no sufren pérdidas de tiempo. Las bibliotecas frp intercambiables generalmente emplean uno de dos esquemas: o bien tienen una "mónada de creación" especial en la que se crean valores FRP, o usan un parámetro de tipo "envejecimiento" para limitar los contextos en los que pueden ocurrir los cambios. elerea (¿y posiblemente netwire?) usan el primero, mientras que el plátano reactivo reciente y el pomelo usan este último.
Con "frp conmutable", me refiero a uno que implementa el switcher :: Behavior a -> Event (Behavior a) -> Behavior a
funciones de Conal switcher :: Behavior a -> Event (Behavior a) -> Behavior a
, o semántica idéntica. Esto significa que la forma de la red puede cambiar dinámicamente a medida que se ejecuta.
En realidad, esto no contradice la declaración de @ertes sobre las interfaces monádicas: resulta que proporcionar una instancia de Monad
para un Event
permite fugas de tiempo, y con cualquiera de los enfoques anteriores ya no es posible definir las instancias de Monad equivalentes.
Finalmente, aunque todavía queda mucho trabajo por hacer con FRP, creo que algunas de las plataformas más nuevas (reactive-banana, elerea, netwire) son estables y lo suficientemente maduras para que puedas construir un código confiable a partir de ellas. Pero es posible que deba dedicar mucho tiempo a aprender los detalles para comprender cómo obtener un buen rendimiento.
Estoy intentando visualizar algunos sistemas físicos automáticos simples (tales como péndulo, brazos de robot, etc.) en Haskell. A menudo esos sistemas se pueden describir mediante ecuaciones como
df/dt = c*f(t) + u(t)
donde u(t)
representa algún tipo de "control inteligente". Esos sistemas parecen encajar muy bien en el paradigma de Programación Reactiva Funcional.
Así que agarré el libro "The Haskell School of Expression" de Paul Hudak, y descubrí que el lenguaje específico de dominio "FAL" (para lenguaje de animación funcional) presentado allí realmente funciona bastante bien para mis sistemas simples de juguete (aunque algunas funciones, especialmente integrate
, parecía ser un poco perezoso para un uso eficiente, pero fácilmente reparable).
Mi pregunta es, ¿cuál es la alternativa más madura, actualizada, bien mantenida y ajustada al rendimiento para aplicaciones más avanzadas o incluso prácticas en la actualidad?
Esta página wiki enumera varias opciones para Haskell, pero no tengo claro los siguientes aspectos:
El estado de "reactivo", el proyecto de Conal Eliott que es (como yo lo entiendo) uno de los inventores de este paradigma de programación, parece un poco rancio. Me encanta su código, pero tal vez debería probar otras alternativas más actualizadas. ¿Cuál es la principal diferencia entre ellos, en términos de sintaxis / rendimiento / estabilidad en tiempo de ejecución?
Para citar una survey de 2011, Sección 6, " ... las implementaciones de FRP aún no son lo suficientemente eficientes o lo suficientemente predecibles en el rendimiento para ser utilizadas de manera efectiva en dominios que requieren garantías de latencia ... ". Aunque la encuesta sugiere algunas optimizaciones posibles interesantes, dado que FRP está allí por más de 15 años, tengo la impresión de que este problema de rendimiento puede ser algo muy difícil o incluso intrínsecamente difícil de resolver al menos dentro de unos pocos años. ¿Es esto cierto?
El mismo autor de la encuesta habla sobre "pérdidas de tiempo" en su blog . ¿Es el problema exclusivo de FRP, o algo que generalmente tenemos cuando programamos en un lenguaje puro y no estricto? ¿Alguna vez te pareció demasiado difícil estabilizar un sistema basado en FRP con el tiempo, si no lo suficientemente eficiente?
¿Sigue siendo este un proyecto de nivel de investigación? ¿Están las personas como ingenieros de planta, ingenieros de robótica, ingenieros financieros, etc. usándolos realmente (en un lenguaje que se adapte a sus necesidades)?
Aunque personalmente prefiero la implementación de Haskell, estoy abierto a otras sugerencias. Por ejemplo, sería particularmente divertido tener una implementación de Erlang: ¡entonces sería muy fácil tener un proceso de servidor inteligente, adaptable y de autoaprendizaje!
En este momento, existen principalmente dos bibliotecas Haskell prácticas para la programación reactiva funcional. Ambos son mantenidos por personas solteras, pero también reciben contribuciones de otros programadores Haskell:
Netwire centra en la eficiencia, la flexibilidad y la previsibilidad. Tiene su propio paradigma de eventos y se puede usar en áreas donde el FRP tradicional no funciona, incluidos los servicios de red y las simulaciones complejas. Estilo: aplicativo y / o con flecha. Autor inicial y mantenedor: Ertugrul Söylemez (este soy yo).
reactive-banana basa en el paradigma FRP tradicional. Si bien es práctico de usar, también sirve como base para la investigación clásica FRP. Su foco principal está en las interfaces de usuario y hay una interfaz preparada para wx. Estilo: aplicativo. Autor inicial y mantenedor: Heinrich Apfelmus.
Deberías probarlos a ambos, pero dependiendo de tu aplicación probablemente encuentres uno u otro para que se ajuste mejor.
Para juegos, redes, control de robots y simulaciones, Netwire te resultará útil. Viene con cables listos para esas aplicaciones, que incluyen varios diferenciales útiles, integrales y mucha funcionalidad para el manejo transparente de eventos. Para ver un tutorial, visite la documentación del módulo Control.Wire
en la página que he vinculado.
Para las interfaces gráficas de usuario actualmente su mejor opción es reactive-banana. Ya tiene una interfaz wx (como una biblioteca separada reactive-banana-wx) y Heinrich bloguea mucho sobre FRP en este contexto, incluidas muestras de código.
Para responder a sus otras preguntas: FRP no es adecuado en escenarios en los que necesita previsibilidad en tiempo real. Esto se debe en gran parte a Haskell, pero desafortunadamente FRP es difícil de realizar en idiomas de nivel inferior. Tan pronto como Haskell se convierta en tiempo real, FRP también llegará allí. Conceptualmente Netwire está listo para aplicaciones en tiempo real.
Las filtraciones de tiempo ya no son un problema, porque están relacionadas en gran medida con el marco monádico. Las implementaciones prácticas de FRP simplemente no ofrecen una interfaz monádica. Yampa ha comenzado esto y Netwire y reactivo-banana se basan en eso.
No conozco ningún proyecto comercial o de gran escala que use FRP en este momento. Las bibliotecas están listas, pero creo que la gente aún no lo está.
Voy a enumerar un par de elementos en el espacio Mono y .Net y uno del espacio Haskell que encontré no hace mucho tiempo. Comenzaré con Haskell.
Olmo - link
Su descripción según su sitio:
Elm tiene como objetivo hacer el desarrollo web front-end más agradable. Introduce un nuevo enfoque para la programación de la GUI que corrige los problemas sistémicos de HTML, CSS y JavaScript. Elm le permite trabajar rápida y fácilmente con el diseño visual, usar el lienzo, administrar la entrada complicada del usuario y escapar del infierno de devolución de llamada.
Tiene su propia variante de FRP . De jugar con sus ejemplos parece bastante maduro.
Extensiones Reactivas - link
Descripción de su página principal:
The Reactive Extensions (Rx) es una biblioteca para componer programas asincrónicos y basados en eventos que utilizan secuencias observables y operadores de consultas estilo LINQ. Al usar Rx, los desarrolladores representan flujos de datos asíncronos con Observables, consultan flujos de datos asincrónicos utilizando operadores LINQ y parametrizan la concurrencia en las secuencias de datos asíncronas usando Schedulers. En pocas palabras, Rx = Observables + LINQ + Programadores.
Reactive Extensions proviene de MSFT e implementa muchos excelentes operadores que simplifican el manejo de eventos. Fue abierto desde hace solo un par de días. Es muy maduro y se usa en producción; en mi opinión, hubiera sido una API más agradable para las API de Windows 8 que la que proporciona la biblioteca TPL; porque los observables pueden ser tanto calientes como fríos y reintentados / fusionados, etc., mientras que las tareas siempre representan cálculos calientes o realizados que se ejecutan, fallan o se completan.
Escribí el código del lado del servidor usando Rx para asynchronocity, pero debo admitir que escribir funcionalmente en C # puede ser un poco molesto. F # tiene un par de contenedores, pero ha sido difícil rastrear el desarrollo de API, porque el grupo está relativamente cerrado y MSFT no lo promociona como lo hacen otros proyectos.
Su fuente abierta vino con la fuente abierta de su compilador IL-a-JS, por lo que probablemente podría funcionar bien con JavaScript o Elm.
Probablemente podrías unir F # / C # / JS / Haskell muy bien usando un intermediario de mensajes, como RabbitMQ y SocksJS.
Bling UI Toolkit - link
Descripción de su página principal:
Bling es una biblioteca basada en C # para programar fácilmente imágenes, animaciones, interacciones y visualizaciones en WPF / .NET de Microsoft. Bling está orientado a los tecnólogos del diseño, es decir, a los diseñadores que a veces programan, para ayudar en la rápida creación de prototipos de ideas de diseño de IU. Los estudiantes, artistas, investigadores y aficionados también encontrarán Bling útil como una herramienta para expresar rápidamente ideas o visualizaciones. Las API y construcciones de Bling están optimizadas para la rápida programación del código throw away en lugar de la programación cuidadosa del código de producción.
Artículo LtU-article cortesía.
He probado esto, pero no he trabajado con él para un proyecto de cliente. Se ve increíble, tiene una buena sobrecarga del operador C # que forma los enlaces entre los valores. Utiliza las propiedades de dependencia en WPF / SL / (WinRT) como orígenes de eventos. Sus animaciones 3D funcionan bien en hardware razonable. Usaría esto si termino en un proyecto que necesita visualizaciones; probablemente portándolo a Windows 8.
ReactiveUI - link
Paul Betts, anteriormente en MSFT, ahora en Github, escribió ese marco. He trabajado bastante extensamente y me gusta el modelo. Está más desacoplado que Blink (por su naturaleza al usar Rx y sus abstracciones), lo que facilita el uso del código de prueba unitaria. El cliente github git para Windows está escrito en esto.
Comentarios
El modelo reactivo es lo suficientemente eficiente para la mayoría de las aplicaciones que demandan rendimiento. Si está pensando en tiempo real, apostaría que la mayoría de los lenguajes de GC tienen problemas. Rx, ReactiveUI crea una cantidad de objeto pequeño que se debe censurar, porque así es como se crean / eliminan las suscripciones y se avanzan los valores intermedios en la "mónada" reactiva de las devoluciones de llamada. En general en .Net prefiero la programación reactiva sobre la programación basada en tareas porque las devoluciones de llamadas son estáticas (conocidas en tiempo de compilación, sin asignación) mientras las tareas se asignan dinámicamente (no se conoce, todas las llamadas necesitan una instancia, basura creada) y se compilan lambdas clases generadas por el compilador
Obviamente C # y F # son estrictamente evaluados, por lo que la fuga de tiempo no es un problema aquí. Lo mismo para JS. Sin embargo, puede ser un problema con los observables reproducibles o en caché.