J'ai récemment attrapé le bug FP (en essayant d'apprendre Haskell), et j'ai été vraiment impressionné par ce que j'ai vu jusqu'à présent (fonctions de première classe, évaluation paresseuse et tous les autres goodies). Je ne suis pas encore un expert, mais j'ai déjà commencé à trouver plus facile de raisonner "fonctionnellement" qu'impérativement pour les algorithmes de base (et j'ai du mal à revenir là où je dois).
Le seul domaine où la PF actuelle semble tomber à plat, cependant, est la programmation GUI. L'approche Haskell semble consister simplement à envelopper des kits d'outils GUI impératifs (tels que GTK + ou wxWidgets) et à utiliser des blocs "do" pour simuler un style impératif. Je n'ai pas utilisé F #, mais ma compréhension est qu'il fait quelque chose de similaire en utilisant OOP avec les classes .NET. De toute évidence, il y a une bonne raison à cela - la programmation actuelle de l'interface graphique concerne les E / S et les effets secondaires, donc la programmation purement fonctionnelle n'est pas possible avec la plupart des frameworks actuels.
Ma question est, est-il possible d'avoir une approche fonctionnelle de la programmation GUI? J'ai du mal à imaginer à quoi cela ressemblerait dans la pratique. Quelqu'un connaît-il des cadres, expérimentaux ou non, qui essaient ce genre de chose (ou même des cadres conçus à partir de zéro pour un langage fonctionnel)? Ou la solution consiste-t-elle à utiliser simplement une approche hybride, avec OOP pour les parties GUI et FP pour la logique? (Je demande juste par curiosité - j'adorerais penser que FP est "l'avenir", mais la programmation GUI semble être un assez grand trou à combler.)
Réponses:
Ce n'est pas vraiment "l'approche Haskell" - c'est juste la façon dont vous vous connectez le plus directement aux kits d'outils GUI impératifs - via une interface impérative. Haskell se trouve juste avoir des reliures assez importantes.
Il existe plusieurs approches modérément matures ou plus expérimentales purement fonctionnelles / déclaratives des interfaces graphiques, principalement dans Haskell, et utilisant principalement la programmation réactive fonctionnelle.
Quelques exemples sont:
Pour ceux d'entre vous qui ne sont pas familiers avec Haskell, Flapjax, http://www.flapjax-lang.org/ est une implémentation de programmation réactive fonctionnelle en plus de JavaScript.
la source
Les mots clés que vous recherchez sont "programmation réactive fonctionnelle" (FRP).
Conal Elliott et quelques autres ont fait un peu d'une industrie artisanale en essayant de trouver la bonne abstraction pour FRP. Il existe plusieurs implémentations des concepts FRP dans Haskell.
Vous pourriez envisager de commencer par le plus récent article de Conal "Push-Pull Functional Reactive Programming" de Conal , mais il existe plusieurs autres implémentations (plus anciennes), certaines liées depuis le site haskell.org . Conal a le don de couvrir tout le domaine et son article peut être lu sans référence à ce qui l'a précédé.
Pour avoir une idée de la façon dont cette approche peut être utilisée pour le développement d'interface graphique, vous voudrez peut-être regarder Fudgets , qui, bien qu'il soit un peu long dans la dent ces jours-ci, étant conçu au milieu des années 90, présente une approche FRP solide à la conception GUI.
la source
Windows Presentation Foundation est une preuve que l'approche fonctionnelle fonctionne très bien pour la programmation GUI. Il présente de nombreux aspects fonctionnels et un "bon" code WPF (recherche de modèle MVVM) met l'accent sur l'approche fonctionnelle plutôt que sur l'impératif. Je pourrais courageusement affirmer que WPF est la boîte à outils GUI fonctionnelle la plus réussie :-)
WPF décrit l'interface utilisateur en XAML (bien que vous puissiez également la réécrire en regardant fonctionnellement C # ou F #), donc pour créer une interface utilisateur, vous écririez:
De plus, WPF vous permet également de décrire de manière déclarative les animations et les réactions aux événements en utilisant un autre ensemble de balises déclaratives (encore une fois, la même chose peut être écrite en code C # / F #):
En fait, je pense que WPF a beaucoup de choses en commun avec le FRP de Haskell (bien que je pense que les concepteurs de WPF ne connaissaient pas FRP et c'est un peu malheureux - WPF se sent parfois un peu bizarre et peu clair si vous utilisez la fonctionnalité point de vue).
la source
INotifyPropertyChanged
de toutes choses), me semble contraire à FP. Je ne suis certainement pas un expert en FP, et je me concentre peut-être trop sur l'aspect immuabilité par opposition à l'aspect déclaratif, mais j'ai du mal à voir comment le modèle MVVM (tel qu'il est généralement utilisé) est un exemple de FP.INotifyPropertyChanged
est juste une fonction de mise à jour que vous transmettez partout où vous avez besoin de gérer les mises à jour de l'interface graphique - c'est un correctif de latence.Je dirais en fait que la programmation fonctionnelle (F #) est un bien meilleur outil pour la programmation d'interface utilisateur que par exemple C #. Vous avez juste besoin de penser le problème un peu différemment.
Je discute de ce sujet dans mon livre de programmation fonctionnelle au chapitre 16, mais il y a un extrait gratuit disponible , qui montre ( à mon humble avis) le modèle le plus intéressant que vous pouvez utiliser en F #. Supposons que vous souhaitiez implémenter le dessin de rectangles (l'utilisateur appuie sur le bouton, déplace la souris et relâche le bouton). En F #, vous pouvez écrire quelque chose comme ceci:
Il s'agit d'une approche très impérative (dans le style pragmatique habituel F #), mais elle évite d'utiliser l'état mutable pour stocker l'état actuel du dessin et pour stocker l'emplacement initial. Cela peut être rendu encore plus fonctionnel, j'ai écrit une bibliothèque qui fait cela dans le cadre de ma thèse de master, qui devrait être disponible sur mon blog dans les deux prochains jours.
La programmation réactive fonctionnelle est une approche plus fonctionnelle, mais je la trouve un peu plus difficile à utiliser car elle repose sur des fonctionnalités Haskell assez avancées (comme les flèches). Cependant, il est très élégant dans un grand nombre de cas. Sa limitation est que vous ne pouvez pas facilement encoder une machine à états (qui est un modèle mental utile pour les programmes réactifs). C'est très facile en utilisant la technique F # ci-dessus.
la source
IObservable
.Que vous soyez dans un langage hybride fonctionnel / OO comme F # ou OCaml, ou dans un langage purement fonctionnel comme Haskell où les effets secondaires sont relégués à la monade IO, c'est généralement le cas qu'une tonne de travail est nécessaire pour gérer une interface graphique ressemble beaucoup plus à un "effet secondaire" qu'à un algorithme purement fonctionnel.
Cela dit, des recherches très solides ont été les interfaces graphiques fonctionnelles . Il existe même des boîtes à outils (principalement) fonctionnelles telles que Fudgets ou FranTk .
la source
Vous pouvez consulter la série de Don Syme sur F # où il fait une démo en créant un gui. le lien suivant est vers la troisième partie de la série (vous pouvez lier de là aux deux autres parties).
Utiliser F # pour le développement WPF serait un paradigme GUI très intéressant ...
http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-3-of-3/
la source
L'une des idées révélatrices de la programmation fonctionnelle réactive est d'avoir une fonction de gestion des événements produisant à la fois une réaction aux événements ET la prochaine fonction de gestion des événements. Ainsi, un système en évolution est représenté comme une séquence de fonctions de gestion d'événements.
Pour moi, l'apprentissage de Yampa est devenu un point crucial pour obtenir correctement cette fonction de production de fonctions. Il y a de beaux papiers sur Yampa. Je recommande The Yampa Arcade:
http://www.cs.nott.ac.uk/~nhn/Talks/HW2003-YampaArcade.pdf (diapositives, PDF) http://www.cs.nott.ac.uk/~nhn/Publications/hw2003. pdf (article complet, PDF)
Il y a une page wiki sur Yampa sur Haskell.org
http://www.haskell.org/haskellwiki/Yampa
Page d'accueil Yampa originale:
http://www.haskell.org/yampa (malheureusement cassé pour le moment)
la source
Depuis que cette question a été posée pour la première fois, la programmation réactive fonctionnelle a été rendue un peu plus courante par Elm.
Je suggère de le vérifier sur http://elm-lang.org , qui propose également d'excellents didacticiels interactifs sur la façon de créer une interface graphique entièrement fonctionnelle dans le navigateur.
Il vous permet de créer des interfaces graphiques entièrement fonctionnelles où le code que vous devez fournir vous-même n'est composé que de fonctions pures. Personnellement, je l'ai trouvé beaucoup plus facile à utiliser que les différents cadres de l'interface graphique Haskell.
la source
Le discours d'Elliot sur FRP peut être trouvé ici .
De plus, pas vraiment une réponse mais une remarque et quelques réflexions : en quelque sorte le terme "GUI fonctionnel" ressemble un peu à un oxymore (pureté et IO dans le même terme).
Mais ma compréhension vague est que la programmation d'interface graphique fonctionnelle consiste à définir de manière déclarative une fonction dépendante du temps qui prend l'entrée utilisateur dépendante du temps (réel) et produit une sortie GUI dépendante du temps.
En d'autres termes, cette fonction est définie comme une équation différentielle de manière déclarative, plutôt que par un algorithme utilisant impérativement un état mutable.
Ainsi, dans FP conventionnel, on utilise des fonctions indépendantes du temps, tandis que dans FRP, on utilise des fonctions dépendantes du temps comme blocs de construction pour décrire un programme.
Pensons à simuler une balle sur un ressort avec lequel l'utilisateur peut interagir. La position de la balle est la sortie graphique (sur l'écran), l'utilisateur poussant la balle est une touche (entrée).
La description de ce programme de simulation en FRP (selon ma compréhension) se fait par une seule équation différentielle (déclarative): accélération * masse = - étirement du ressort * constante du ressort + Force exercée par l'utilisateur.
Voici une vidéo sur ELM qui illustre ce point de vue.
la source
En 2016, il existe plusieurs autres cadres FRP relativement matures pour Haskell tels que Sodium et Reflex (mais aussi Netwire).
Le livre de Manning sur la programmation réactive fonctionnelle présente la version Java de Sodium, pour des exemples de travail, et illustre comment une base de code GUI FRP se comporte et évolue par rapport aux approches impératives et basées sur les acteurs.
Il y a aussi un article récent sur le FRP Arrowized et la perspective d'incorporer les effets secondaires, les IO et les mutations dans un cadre de FRP pur et respectueux de la loi: http://haskell.cs.yale.edu/wp-content/uploads/2015/10/ dwc-yale-formated-dissertation.pdf .
Il convient également de noter que les frameworks JavaScript tels que ReactJS et Angular et bien d'autres sont déjà ou s'orientent vers l'utilisation d'un FRP ou d'une approche fonctionnelle pour réaliser des composants GUI évolutifs et composables.
la source
Les langages de balisage comme XUL vous permettent de créer une interface graphique de manière déclarative.
la source
Pour résoudre ce problème, j'ai publié mes réflexions sur l'utilisation de F #,
http://fadsworld.wordpress.com/2011/04/13/f-in-the-enterprise-i/ http://fadsworld.wordpress.com/2011/04/17/fin-the-enterprise-ii- 2 /
Je prévois également de faire un tutoriel vidéo pour terminer la série et montrer comment F # peut contribuer à la programmation UX.
Je ne parle que dans le contexte de F # ici.
-Fahad
la source
Toutes ces autres réponses reposent sur une programmation fonctionnelle, mais prennent beaucoup de leurs propres décisions de conception. Une bibliothèque qui est construite essentiellement entièrement à partir de fonctions et de types de données abstraits simples est
gloss
. Voici le type de saplay
fonction à partir de la sourceComme vous pouvez le voir, cela fonctionne entièrement en fournissant des fonctions pures avec des types abstraits simples, que d'autres bibliothèques vous aident.
la source
L'innovation la plus apparente remarquée par les nouveaux venus à Haskell est qu'il existe une séparation entre le monde impur qui s'intéresse à la communication avec le monde extérieur et le monde pur du calcul et des algorithmes. Une question fréquente pour les débutants est "Comment puis-je me débarrasser
IO
, c'est-à-dire se convertirIO a
ena
?" Le moyen d'y parvenir est d'utiliser des monades (ou d'autres abstractions) pour écrire du code qui effectue des effets d'E / S et des chaînes. Ce code rassemble des données du monde extérieur, en crée un modèle, effectue certains calculs, éventuellement en utilisant du code pur, et génère le résultat.En ce qui concerne le modèle ci-dessus, je ne vois rien de mal à manipuler les interfaces graphiques dans la
IO
monade. Le plus gros problème qui découle de ce style est que les modules ne sont plus composables, c'est-à-dire que je perds la plupart de mes connaissances sur l'ordre d'exécution global des instructions dans mon programme. Pour le récupérer, je dois appliquer un raisonnement similaire à celui du code GUI impératif simultané. Pendant ce temps, pour un code impur non GUI, l'ordre d'exécution est évident en raison de la définition de l' opérateur de laIO
monade>==
(au moins tant qu'il n'y a qu'un seul thread). Pour le code pur, cela n'a pas d'importance du tout, sauf dans les cas d'angle pour augmenter les performances ou pour éviter des évaluations entraînant⊥
.La plus grande différence philosophique entre console et IO graphique est que les programmes implémentant le premier sont généralement écrits dans un style synchrone. Ceci est possible car il n'y a (en laissant de côté les signaux et autres descripteurs de fichiers ouverts) qu'une seule source d'événements: le flux d'octets communément appelé
stdin
. Les interfaces graphiques sont cependant intrinsèquement asynchrones et doivent réagir aux événements du clavier et aux clics de souris.Une philosophie populaire consistant à effectuer des E / S asynchrones de manière fonctionnelle est appelée programmation réactive fonctionnelle (FRP). Il a obtenu beaucoup de traction récemment dans des langages impurs et non fonctionnels grâce à des bibliothèques telles que ReactiveX et des frameworks tels que Elm. En un mot, c'est comme visualiser les éléments de l'interface graphique et d'autres choses (comme les fichiers, les horloges, les alarmes, le clavier, la souris) en tant que sources d'événements, appelées "observables", qui émettent des flux d'événements. Ces événements sont combinés à l' aide des opérateurs familiers tels que
map
,foldl
,zip
,filter
,concat
,join
, etc., pour produire de nouveaux flux. Ceci est utile car l'état du programme lui-même peut être vu commescanl . map reactToEvents $ zipN <eventStreams>
du programme, oùN
est égal au nombre d'observables jamais pris en compte par le programme.Travailler avec des observables FRP permet de récupérer la composabilité car les événements d'un flux sont ordonnés dans le temps. La raison en est que l'abstraction du flux d'événements permet de visualiser tous les observables sous forme de boîtes noires. En fin de compte, la combinaison de flux d'événements à l'aide d'opérateurs redonne un ordre local lors de l'exécution. Cela m'oblige à être beaucoup plus honnête sur les invariants sur lesquels mon programme s'appuie réellement, de la même manière que toutes les fonctions de Haskell doivent être référentiellement transparentes: si je veux extraire des données d'une autre partie de mon programme, je dois être explicite annonce un type approprié pour mes fonctions. (La monade IO, étant un langage spécifique au domaine pour écrire du code impur, contourne efficacement cela)
la source
La programmation fonctionnelle a peut-être évolué depuis que j'étais à l'université, mais si je me souviens, le point principal d'un système de programmation fonctionnelle était d'empêcher le programmeur de créer un «effet secondaire». Cependant, les utilisateurs achètent des logiciels en raison des effets secondaires qui sont créés, par exemple la mise à jour d'une interface utilisateur.
la source