{"id":13727974,"url":"https://github.com/keera-studios/keera-hails","last_synced_at":"2025-04-06T16:14:22.713Z","repository":{"id":3610070,"uuid":"4675069","full_name":"keera-studios/keera-hails","owner":"keera-studios","description":"Keera Hails: Haskell on Rails - Reactive Programming Framework for Interactive Haskell applications","archived":false,"fork":false,"pushed_at":"2022-04-05T08:30:03.000Z","size":1447,"stargazers_count":198,"open_issues_count":9,"forks_count":12,"subscribers_count":15,"default_branch":"develop","last_synced_at":"2025-03-30T15:08:47.426Z","etag":null,"topics":["android","frp","functional-reactive-programming","ghcjs","gtk","haskell","ios","mvc","qt","reactive-values","rvs","web","wx","yampa"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/keera-studios.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-06-15T12:44:50.000Z","updated_at":"2025-02-15T05:35:33.000Z","dependencies_parsed_at":"2022-09-10T22:40:10.918Z","dependency_job_id":null,"html_url":"https://github.com/keera-studios/keera-hails","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keera-studios%2Fkeera-hails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keera-studios%2Fkeera-hails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keera-studios%2Fkeera-hails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keera-studios%2Fkeera-hails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/keera-studios","download_url":"https://codeload.github.com/keera-studios/keera-hails/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247509237,"owners_count":20950232,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","frp","functional-reactive-programming","ghcjs","gtk","haskell","ios","mvc","qt","reactive-values","rvs","web","wx","yampa"],"created_at":"2024-08-03T02:00:35.692Z","updated_at":"2025-04-06T16:14:22.697Z","avatar_url":"https://github.com/keera-studios.png","language":"Haskell","funding_links":[],"categories":["👓 Alternatives to the [Electron.js](https://electronjs.org) ⚛"],"sub_categories":["Haskell"],"readme":"# Keera Hails\n[![Build Status](https://travis-ci.org/keera-studios/keera-hails.svg?branch=master)](https://travis-ci.org/keera-studios/keera-hails)\n\nKeera Hails is a toolkit to create *Reactive Applications in Haskell*.\nIt facilitates combining User Interfaces, external devices, network\nconnections, files and, optionally, FRP networks.\n\nKeera Hails is modular and extensible. It is cross platform (Windows, Linux,\nMacOSX, iOS, Android, GHCJS), UI-agnostic (Gtk+, WX, Qt, iOS native UIs,\nAndroid Native toolkit, HTML DOM), FRP-agnostic and device-agnostic (Wiimote,\nWebcams, etc).\n\nKeera Hails has been used to create large applications and is used commercially\nin production.\n\n# At a glance\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n    \u003cp align=\"center\"\u003e\n      Keera Studios' Gale Studio!\n      \u003cbr /\u003e\u003cbr /\u003e\n      \u003ca href=\"http://keera.co.uk\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://keera.co.uk/wp-content/uploads/2011/10/Screenshot.png\" height=\"auto\" alt=\"Gale Studio screenshot\" style=\"max-height:175px;\"\u003e\u003c/a\u003e\n      \u003cimg width=\"441\" height=\"1\"\u003e\n      \u003cbr /\u003e\n    \u003c/p\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n    \u003cp align=\"center\"\u003e\n      Guerric Chupin's Arpeggigon\n      \u003cbr /\u003e\u003cbr /\u003e\n      \u003ca href=\"https://gitlab.com/chupin/arpeggigon\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://keera.co.uk/wp-content/uploads/2020/05/arpeggigon.png\" height=\"auto\" alt=\"Arpeggigon screenshot\" style=\"max-height:175px;\"\u003e\u003c/a\u003e\n      \u003cimg width=\"441\" height=\"1\"\u003e\n      \u003cbr /\u003e\n    \u003c/p\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n    \u003cp align=\"center\"\u003e\n      SoOSim simulator\n      \u003cbr /\u003e\n      \u003cbr /\u003e\n      \u003cimg src=\"https://keera.co.uk/wp-content/uploads/2011/10/Screenshot-from-2014-09-24-142046.png\" height=\"auto\" alt=\"CAES group's SoOSim\" style=\"max-height: 175px;\"\u003e\n      \u003cimg width=\"441\" height=\"1\"\u003e\n      \u003cbr /\u003e\n    \u003c/p\u003e\n    \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n    \u003cp align=\"center\"\u003e\n      iOS demo\n      \u003cbr /\u003e\u003cbr /\u003e\n      \u003ca href=\"http://keera.co.uk\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://keera.co.uk/wp-content/uploads/2022/04/keera-hails-ios-demo-capture.gif\" height=\"auto\" alt=\"Keera Hails iOS demo app screenshot\" style=\"max-height:175px;\"\u003e\u003c/a\u003e\n      \u003cimg width=\"441\" height=\"1\"\u003e\n      \u003cbr /\u003e\n    \u003c/p\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n    \u003cp align=\"center\"\u003e\n      Android demo\n      \u003cbr /\u003e\u003cbr /\u003e\n      \u003ca href=\"http://keera.co.uk\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://keera.co.uk/wp-content/uploads/2022/04/keera-hails-android-demo-capture.gif\" height=\"auto\" alt=\"Keera Hails Android demo app screenshot\" style=\"max-height:175px;\"\u003e\u003c/a\u003e\n      \u003cimg width=\"441\" height=\"1\"\u003e\n      \u003cbr /\u003e\n    \u003c/p\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n    \u003cp align=\"center\"\u003e\n      Web demo\n      \u003cbr /\u003e\n      \u003cbr /\u003e\n      \u003ca href=\"http://keera.co.uk\" target=\"_blank\"\u003e\n      \u003cimg src=\"https://keera.co.uk/wp-content/uploads/2022/04/hello-hails-web-calculator-css-final-orig-midres-short.gif\" height=\"auto\" alt=\"Keera Hails web demo app capture\" style=\"max-height: 175px;\"\u003e\u003c/a\u003e\n      \u003cimg width=\"441\" height=\"1\"\u003e\n      \u003cbr /\u003e\n    \u003c/p\u003e\n    \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n    \u003ctd colspan=\"3\"\u003e\n      \u003csub\u003e\n        \u003csup\u003e\n\t  Image from Gale Studio and Keera Hails demos are Copyright © 2011 -\n\t  2022 Keera Studios Ltd. All Rights Reserved. Keera, Keera Studios,\n          Keera Hails, Gale, Gale Studio are trademarks of Keera Studios Ltd.\n        \u003c/sup\u003e\n      \u003c/sub\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n# Hands-on example\n\nThe two key ideas in Keera Hails are *Reactive Values* and *Reactive Rules*.\nReactive values are data holders or action endpoints that will contain, provide\nand/or consume data.  Reactive Rules just connect these values so that changes\npropagate across.\n\nA very simple example of an RV is the following construction, in which a passive\n`IORef` is turned into active Reactive Value.\n\n```haskell\ndo\n\n  -- Empower IORef with callback installation mechanism. This comes from the\n  -- keera-callbacks library.\n  --\n  -- passiveCBRef :: CBRRef Integer\n  passiveCBRef \u003c- newCBRef 0\n\n  -- Turn IO Ref into active reactive value (RV).\n  --\n  -- RVs are type classes. We use the type of Reactive Fields, which have a\n  -- trivial RV implementation.\n  let activeCBRefRV :: ReactiveFieldReadWrite IO Integer\n      activeCBRefRV = ReactiveFieldReadWrite\n                        (writeCBRef           passiveCBRef)\n                        (readCBRef            passiveCBRef)\n                        (installCallbackCBRef passiveCBRef)\n```\n\nWe now define an RV that encloses a trivial monadic action:\n\n```haskell\n  -- do continues\n\n  -- Define a write-only RV that prints whatever you put in it.\n  let printer :: Show a =\u003e ReactiveFieldWrite IO a\n      printer = wrapMW print\n```\n\nYou can connect them together in a monadic environment:\n```haskell\n  -- Connect them using a reactive rule. In a GUI application, this code would\n  -- in the controller, and would define connections between the model and\n  -- the view.\n  --\n  -- For bi-directional connections, see (=:=).\n  activeCBRefRV =:\u003e printer\n```\n\nIf you now loop and put data in the `IORef`, it will be passed along\nthe reactive connection and printed to the output:\n\n```haskell\n  forever $ do\n    threadDelay 1000000 -- 1 second\n    reactiveValueModify activeCBRefRV (+1)\n```\n\nUsing the same, simple ideas, you can define a RVs for, and connect, the fields\nof GUI widgets, for files, for network sockets, etc.\n\n# Project Structure\n\nThe toolkit is divided in three parts:\n* Reactive Values: they are typed mutable values with event dispatching and\naccess properties. They can be modified by lifting functions and applying\nlenses to them. They can also be connected so that they stay in sync during\nprogram execution.\n\n  - [keera-hails-reactivevalues](keera-hails-reactivevalues/): basic definitions and RV manipulation.\n  - [keera-hails-reactivelenses](keera-hails-reactivelenses/): lens application.\n\n* Reactive bindings: Widget properties/attributes can be seen as\nreactive values. So can network sockets, files, application models ('model'\nas in MVC) and external resources (polling). Uni-directional, Functional\nReactive Programming signal functions can also be wrapped into a pair\nof RVs (see Yampa). The idea is that, at the highest application level\n(controller), each layer is wrapped in a reactive container and connected\nto others.\n\n  - [keera-hails-reactive-fs](keera-hails-reactive-fs/): Files as RVs\n  - [keera-hails-reactive-network](keera-hails-reactive-network/): Sockets as RVs\n  - [keera-hails-reactive-gtk](keera-hails-reactive-gtk/): Widget attributes and events as RVs\n  - [keera-hails-reactive-wx](keera-hails-reactive-wx/): Widget attributes and events as RVs\n  - [keera-hails-reactive-qt](keera-hails-reactive-qt/): Widget attributes and events as RVs\n  - [keera-hails-reactive-htmldom](keera-hails-reactive-htmldom/) (via GHCJS): HTML DOM element properties as RVs\n  - [keera-hails-reactive-yampa](keera-hails-reactive-yampa/): Yampa reactimation loops as a pair of RVs\n  - [keera-hails-reactive-polling](keera-hails-reactive-polling/): Strategies to make RVs fire regularly\n\n  Backends for iOS and Android (using each platform's native UI toolkits) are\nalso available. Samples can be found\n[here](https://www.facebook.com/keerastudios/videos/1674596312555888/) and\n[here](https://www.facebook.com/keerastudios/photos/a.550237501658447.138031.300854939930039/1675515659130620/?type=3\u0026theater).\nPlease contact Keera Studios if you wish to use them.\n\n* MVC Architecture\n\n  MVC is easily applied using hails. There are two easy ways of wraping pure\n  models into RVs, depending on the level of change detection we need to detect\n  and optimise.\n  - [keera-hails-mvc-model-lightmodel](keera-hails-mvc-model-lightmodel/): Pure\n    models as RVs\n  - [keera-hails-mvc-model-protectedmodels](keera-hails-mvc-model-protectedmodels/):\n    Pure models as RVs, with advance change detection. Template Haskell can be\n\tused to generate model access RVs based on record fields that stop\n    unnecessary change propagation.\n  - [keera-hails-mvc-view](keera-hails-mvc-view/): Interface to the View of any\n    program\n  - [keera-hails-mvc-controller](keera-hails-mvc-controller/): Simple controller-handling definitions.\n\n  A pair Model-View, often needed by the controller, can be wrapped in an\n  *environment*.  The following packages implement a Gtk View and a Gtk\n  environment.\n  - [keera-hails-mvc-view-gtk](keera-hails-mvc-view-gtk/): Structure to wrap Gtk views.\n  - [keera-hails-mvc-environment-gtk](keera-hails-mvc-environment-gtk/): A MVC triplet based on a Gtk View.\n\n  The following package generate default project skeletons that do \"the right\n  thing\" (currently for Gtk+ only). The application takes the approach of\n  \"convention over configuration\": certain modules will be expected to have\n  predetermined names. If this is much of a problem, open a bug report.\n  - [keera-hails](keera-hails/): Program that generates a project skeleton.\n\n  We have a [separate README](demos/keera-hails-gtk-app/) that shows how to\n  build your first app using `keera-hails`.\n\n* Applications can be simplified further. The following packages implement\n  Gtk-based choreographies (M-V synchronizations and controller rule templates)\n  and address other common features needed in applications.\n\n  - [keera-hails-mvc-solutions-gtk](keera-hails-mvc-solutions-gtk/): Advanced choreographies for Gtk applications.\n  - [keera-hails-mvc-solutions-config](keera-hails-mvc-solutions-config/): Handling configuration files cleanly.\n  - [keera-hails-i18n](keera-hails-i18n/): Handling internationalization\n\n## Tutorials, papers and publications\n\n* [Building a reactive calculator in Haskell](https://keera.co.uk/2020/05/28/building-a-reactive-calculator-in-haskell-1-5/)\n* [The Arpeggigon: Declarative Programming of A Full-Fledged Musical Application (PADL 2017)](http://eprints.nottingham.ac.uk/38657/1/padl2017-techreport.pdf)\n* [Bridging the GUI gap with reactive values and relations (Haskell Symposium 2015)](http://dl.acm.org/citation.cfm?id=2804316)\n* [Readme for Reactive Value library](http://github.com/keera-studios/hails-reactivevalues)\n* [Ivan Perez's 1st PhD report, pages 29 and 40](http://www.cs.nott.ac.uk/~ixp/papers/2014-Perez-1st-year-report.pdf)\n(page 40 is a paper of its own; page 29 is the thesis proposal outlining the\ncore ideas and problems that remain to be solved.)\n* [TFP 2014 Pre-proceedings, pages 59-68](http://www.staff.science.uu.nl/~hage0101/preproceedingstfp2014.pdf)\n* [Reactive Programming using Reactive Values (blog post)](http://keera.co.uk/blog/2014/05/24/reactive-programming-using-reactive-values/)\n\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n    \u003cp align=\"center\"\u003e\n      Building a reactive calculator in Haskell!\n      \u003cbr /\u003e\u003cbr /\u003e\n      \u003ca href=\"https://keera.co.uk/2020/05/28/building-a-reactive-calculator-in-haskell-1-5/\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://keera.co.uk/wp-content/uploads/2022/04/hello-hails-web-calculator-css-final-orig-midres-short.gif\" height=\"auto\" alt=\"Keera Hails web demo app capture\" style=\"max-height:175px;\"\u003e\u003c/a\u003e\n      \u003cimg width=\"441\" height=\"1\"\u003e\n      \u003cbr /\u003e\n      \u003csup\u003eCopyright © 2020 - 2021 Keera Studios Ltd. All Rights Reserved.\u003c/sup\u003e\n      \u003cbr /\u003e\n    \u003c/p\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\nFor bibtex references to these articles, see Publications in http://www.cs.nott.ac.uk/~ixp/.\n\n## Applications and demos\n\n* http://github.com/keera-studios/keera-posture\n* http://github.com/ivanperez-keera/SoOSiM-ui\n* [A simple example using RVs for button clicks, sliders, monadic actions and SDL volume](http://github.com/keera-studios/keera-hails/tree/master/demos/keera-hails-demos-soundplay/src/Main.hs#L41-L58)\n* http://github.com/keera-studios/keera-hails/tree/master/demos/keera-hails-demos-wiimote\n* http://github.com/ivanperez-keera/haskellifi-trayicon\n* http://github.com/ivanperez-keera/keera-diamondcard-sms-trayicon\n\n## Credits\n\nI would like to thank the following people for fruitful discussions and collaborations.\n* Henrik Nilsson\n* Hamish Mackenzie (for helping me create the first GHCJS backend for Hails,\n  and for Gtk2hs).\n* Leuite Stegeman (for helping me create the first GHCJS backend for Hails).\n* Guerric Chupin (for continuing this work and writing Arpeggigon).\n* Arsen Kostenko\n* Emilio Gallego\n* Paolo Capriotti\n* Florent Ballestrieri\n* David McGillicuddy\n* Philip Holzenspies\n* Ian-Woo Kim\n* Atze van der Ploeg\n* Simon Peyton Jones\n* Michał Gajda\n* I thank the audiences of the following talks on Reactive programming and\n  Hails, for patientily listening to me complain about the state of the world\n  and commenting on my work.\n  * Haskell Symposium (2015), Vancouver, colocated with ICFP.\n  * London (2014), Haskell Meetup\n  * Nottingham (2014), FPLAD.\n  * TFP (2014)\n  * FPLab, Nottingham (2013)\n  * CAES Group, UTwente (2013)\n  * Babel Research Group, UPM (2010)\n\n(Note: these people do not necessarily support anything I have to say.)\n\n\u003c!--\n## About the name\n\nKeera Hails was born from several experiments back when I was an MSc student\nand researcher in 2008-2009. Back then, it was clear that it was going to be\ncalled Hails, and I often discussed it with my colleagues by referring to it as\n``Haskell on Rails''. I checked that the name wasn't taken, and so Hails was\nborn. I wrote the first commercial program with this library in 2010, and I've\nbeen using it ever since. Many programs have now been written in Hails\n(including Gale, whose name sounds similar, means something related, and was\nalso not arbitrary).\n\nIn 2012, I received a message clients using the library telling me that they\ncouldn't compile their program anymore. Apparently someone had published a\nlibrary called ``Hails'' on Hackage (my hails was on github, but not on\nhackage). I asked the authors of that library to change its name, but they\nrefused, telling me that they were there first.\n\nIt's sad that we have to have these disputes in such a small community. We both\nthink that we are right, and there is no easy way to resolve this matter\nwithout one of us giving something up.\n\nTo avoid collisions, I call this library Keera Hails in all papers. Because\nthere is no risk of confusion, I use the name Hails in this documentation.\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeera-studios%2Fkeera-hails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkeera-studios%2Fkeera-hails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeera-studios%2Fkeera-hails/lists"}