J'essaie de visualiser quelques systèmes physiques automatiques simples (tels que le pendule, les bras de robot, etc.) dans Haskell. Souvent, ces systèmes peuvent être décrits par des équations comme
df/dt = c*f(t) + u(t)
où u(t)
représente une sorte de «contrôle intelligent». Ces systèmes semblent s'intégrer très bien dans le paradigme de la programmation réactive fonctionnelle.
J'ai donc attrapé le livre "The Haskell School of Expression" de Paul Hudak, et j'ai trouvé que le langage spécifique au domaine "FAL" (pour Functional Animation Language) présenté ici fonctionne en fait assez bien pour mes systèmes de jouets simples (bien que certaines fonctions, notamment integrate
, semblait un peu trop paresseux pour une utilisation efficace, mais facilement réparable).
Ma question est la suivante: quelle est l'alternative la plus mature, à jour, bien entretenue et optimisée pour les applications plus avancées ou même pratiques aujourd'hui?
Cette page wiki répertorie plusieurs options pour Haskell, mais je ne suis pas clair sur les points suivants:
Le statut de «réactif», le projet de Conal Eliott qui est (si je comprends bien) l'un des inventeurs de ce paradigme de programmation, semble un peu dépassé. J'adore son code, mais je devrais peut-être essayer d'autres alternatives plus récentes? Quelle est la principale différence entre eux, en termes de syntaxe / performances / stabilité à l'exécution?
Pour citer une enquête de 2011, section 6, " ... les implémentations de FRP ne sont toujours pas suffisamment efficaces ou suffisamment prévisibles en termes de performances pour être utilisées efficacement dans des domaines qui nécessitent des garanties de latence ... ". Bien que l'enquête suggère quelques optimisations possibles intéressantes, étant donné que FRP est là depuis plus de 15 ans, j'ai l'impression que ce problème de performance pourrait être quelque chose de très ou même intrinsèquement difficile à résoudre au moins dans quelques années. Est-ce vrai?
Le même auteur de l'enquête évoque les "fuites de temps" dans son blog . Le problème est-il propre à FRP, ou quelque chose que nous rencontrons généralement lors de la programmation dans un langage pur et non strict? Avez-vous déjà trouvé trop difficile de stabiliser un système à base de FRP au fil du temps, sinon assez performant?
Est-ce toujours un projet de niveau recherche? Les gens comme les ingénieurs d'usine, les ingénieurs en robotique, les ingénieurs financiers, etc. les utilisent-ils réellement (dans le langage qui correspond à leurs besoins)?
Bien que je préfère personnellement une implémentation Haskell, je suis ouvert à d'autres suggestions. Par exemple, il serait particulièrement amusant d'avoir une implémentation Erlang - il serait alors très facile d'avoir un processus serveur intelligent, adaptatif et auto-apprenant!
Bien qu'il y ait déjà de bonnes réponses, je vais tenter de répondre à vos questions spécifiques.
réactif n'est pas utilisable pour des projets sérieux, en raison de problèmes de fuite de temps. (voir # 3). La bibliothèque actuelle avec le design le plus similaire est reactive-banana, qui a été développée avec réactif comme inspiration, et en discussion avec Conal Elliott.
Bien que Haskell lui-même ne soit pas approprié pour les applications en temps réel dur, il est possible d'utiliser Haskell pour des applications en temps réel souples dans certains cas. Je ne connais pas les recherches actuelles, mais je ne pense pas que ce soit un problème insurmontable. Je soupçonne que des systèmes comme Yampa ou des systèmes de génération de code comme Atom sont peut-être la meilleure approche pour résoudre ce problème.
Une "fuite de temps" est un problème spécifique au FRP commutable. La fuite se produit lorsqu'un système est incapable de libérer d'anciens objets, car il peut en avoir besoin si un basculement se produit à un moment donné dans le futur. Outre une fuite de mémoire (qui peut être assez grave), une autre conséquence est que, lorsque le basculement se produit, le système doit faire une pause pendant que la chaîne des anciens objets est parcourue pour générer l'état actuel.
Les bibliothèques frp non commutables telles que Yampa et les anciennes versions de reactive-banana ne souffrent pas de pertes de temps. Les bibliothèques FRP commutables emploient généralement l'un des deux schémas suivants: soit elles ont une «monade de création» spéciale dans laquelle les valeurs FRP sont créées, soit elles utilisent un paramètre de type «vieillissement» pour limiter les contextes dans lesquels les commutations peuvent se produire. elerea (et éventuellement netwire?) utilisent le premier, tandis que les bananes réactives récentes et le pamplemousse utilisent le second.
Par "frp commutable", j'entends celui qui implémente la fonction de Conal
switcher :: Behavior a -> Event (Behavior a) -> Behavior a
, ou une sémantique identique. Cela signifie que la forme du réseau peut changer de manière dynamique lors de son exécution.Cela ne contredit pas vraiment la déclaration de @ ertes sur les interfaces monadiques: il s'avère que fournir une
Monad
instance pour unEvent
rend possible les fuites de temps, et avec l'une ou l'autre des approches ci-dessus, il n'est plus possible de définir les instances Monad équivalentes.Enfin, bien qu'il reste encore beaucoup de travail à faire avec FRP, je pense que certaines des plates-formes les plus récentes (reactive-banana, elerea, netwire) sont suffisamment stables et matures pour que vous puissiez créer un code fiable à partir d'elles. Mais vous devrez peut-être passer beaucoup de temps à apprendre les tenants et les aboutissants afin de comprendre comment obtenir de bonnes performances.
la source
Je vais énumérer quelques éléments dans l'espace Mono et .Net et un de l'espace Haskell que j'ai trouvé il n'y a pas si longtemps. Je vais commencer par Haskell.
Elm - lien
Sa description selon son site:
Il a sa propre variante de FRP . En jouant avec ses exemples, il semble assez mature.
Extensions réactives - lien
Description de sa première page:
Les extensions réactives proviennent de MSFT et implémentent de nombreux excellents opérateurs qui simplifient la gestion des événements. C'était open source il y a quelques jours à peine. Il est très mature et utilisé en production; à mon avis, cela aurait été une API plus agréable pour les API Windows 8 que celle fournie par la bibliothèque TPL; parce que les observables peuvent être à la fois chauds et froids et réessayés / fusionnés, etc., tandis que les tâches représentent toujours des calculs chauds ou effectués qui sont soit en cours d'exécution, défectueux ou terminés.
J'ai écrit du code côté serveur en utilisant Rx pour l'asynchronisme, mais je dois admettre qu'écrire fonctionnellement en C # peut être un peu ennuyeux. F # a quelques wrappers, mais il a été difficile de suivre le développement de l'API, car le groupe est relativement fermé et n'est pas promu par MSFT comme d'autres projets.
Son open sourcing est venu avec l'open sourcing de son compilateur IL-to-JS, donc il pourrait probablement bien fonctionner avec JavaScript ou Elm.
Vous pourriez probablement lier F # / C # / JS / Haskell très bien en utilisant un courtier de messages, comme RabbitMQ et SocksJS.
Boîte à outils Bling UI - lien
Description de sa première page:
Article LtU gratuit .
J'ai testé cela, mais je n'ai pas travaillé avec pour un projet client. Il a l'air génial, a une belle surcharge d'opérateur C # qui forme les liaisons entre les valeurs. Il utilise les propriétés de dépendance dans WPF / SL / (WinRT) comme sources d'événements. Ses animations 3D fonctionnent bien sur du matériel raisonnable. J'utiliserais ceci si je me retrouve sur un projet ayant besoin de visualisations; probablement en le portant sur Windows 8.
ReactiveUI - lien
Paul Betts, auparavant chez MSFT, maintenant chez Github, a écrit ce cadre. J'ai beaucoup travaillé avec et j'aime le modèle. Il est plus découplé que Blink (de par sa nature de l'utilisation de Rx et de ses abstractions) - ce qui facilite le test unitaire du code en l'utilisant. Le client github git pour Windows y est écrit.
commentaires
Le modèle réactif est suffisamment performant pour la plupart des applications exigeantes en performances. Si vous pensez au temps réel difficile, je parierais que la plupart des langages GC ont des problèmes. Rx, ReactiveUI créent une certaine quantité de petits objets qui doivent être GC, car c'est ainsi que les abonnements sont créés / supprimés et que les valeurs intermédiaires progressent dans la "monade" réactive des rappels. En général sur .Net, je préfère la programmation réactive à la programmation basée sur les tâches car les rappels sont statiques (connus au moment de la compilation, pas d'allocation) tandis que les tâches sont allouées dynamiquement (pas connu, tous les appels nécessitent une instance, des déchets créés) - et les lambdas se compilent en classes générées par le compilateur.
Évidemment, C # et F # sont strictement évalués, donc la fuite de temps n'est pas un problème ici. Idem pour JS. Cela peut cependant être un problème avec les observables rejouables ou mis en cache.
la source
u(t)
et les simulations pourf(t)
. Est-ce le cas pour les implémentations F #?