Keera Hails: Haskell on Rails - Reactive Programming Framework for Interactive Haskell applications
Keera Hails is a toolkit to create Reactive Applications in Haskell. It facilitates combining User Interfaces, external devices, network connections, files and, optionally, FRP networks.
Keera Hails is modular and extensible. It is cross platform (Windows, Linux, MacOSX, iOS, Android, GHCJS), UI-agnostic (Gtk+, WX, Qt, iOS native UIs, Android Native toolkit, HTML DOM), FRP-agnostic and device-agnostic (Wiimote, Webcams, etc).
Keera Hails has been used to create large applications and is used commercially in production.
SoOSim simulator
|
||
Image from Gale Studio and Keera Hails demos are Copyright © 2011 - 2022 Keera Studios Ltd. All Rights Reserved. Keera, Keera Studios, Keera Hails, Gale, Gale Studio are trademarks of Keera Studios Ltd. |
The two key ideas in Keera Hails are Reactive Values and Reactive Rules. Reactive values are data holders or action endpoints that will contain, provide and/or consume data. Reactive Rules just connect these values so that changes propagate across.
A very simple example of an RV is the following construction, in which a passive
IORef
is turned into active Reactive Value.
do
-- Empower IORef with callback installation mechanism. This comes from the
-- keera-callbacks library.
--
-- passiveCBRef :: CBRRef Integer
passiveCBRef <- newCBRef 0
-- Turn IO Ref into active reactive value (RV).
--
-- RVs are type classes. We use the type of Reactive Fields, which have a
-- trivial RV implementation.
let activeCBRefRV :: ReactiveFieldReadWrite IO Integer
activeCBRefRV = ReactiveFieldReadWrite
(writeCBRef passiveCBRef)
(readCBRef passiveCBRef)
(installCallbackCBRef passiveCBRef)
We now define an RV that encloses a trivial monadic action:
-- do continues
-- Define a write-only RV that prints whatever you put in it.
let printer :: Show a => ReactiveFieldWrite IO a
printer = wrapMW print
You can connect them together in a monadic environment:
-- Connect them using a reactive rule. In a GUI application, this code would
-- in the controller, and would define connections between the model and
-- the view.
--
-- For bi-directional connections, see (=:=).
activeCBRefRV =:> printer
If you now loop and put data in the IORef
, it will be passed along
the reactive connection and printed to the output:
forever $ do
threadDelay 1000000 -- 1 second
reactiveValueModify activeCBRefRV (+1)
Using the same, simple ideas, you can define a RVs for, and connect, the fields of GUI widgets, for files, for network sockets, etc.
The toolkit is divided in three parts:
Reactive Values: they are typed mutable values with event dispatching and access properties. They can be modified by lifting functions and applying lenses to them. They can also be connected so that they stay in sync during program execution.
Reactive bindings: Widget properties/attributes can be seen as reactive values. So can network sockets, files, application models ('model' as in MVC) and external resources (polling). Uni-directional, Functional Reactive Programming signal functions can also be wrapped into a pair of RVs (see Yampa). The idea is that, at the highest application level (controller), each layer is wrapped in a reactive container and connected to others.
Backends for iOS and Android (using each platform's native UI toolkits) are also available. Samples can be found here and here. Please contact Keera Studios if you wish to use them.
MVC Architecture
MVC is easily applied using hails. There are two easy ways of wraping pure models into RVs, depending on the level of change detection we need to detect and optimise.
A pair Model-View, often needed by the controller, can be wrapped in an environment. The following packages implement a Gtk View and a Gtk environment.
The following package generate default project skeletons that do "the right thing" (currently for Gtk+ only). The application takes the approach of "convention over configuration": certain modules will be expected to have predetermined names. If this is much of a problem, open a bug report.
We have a separate README that shows how to
build your first app using keera-hails
.
Applications can be simplified further. The following packages implement Gtk-based choreographies (M-V synchronizations and controller rule templates) and address other common features needed in applications.
Building a reactive calculator in Haskell!
|
For bibtex references to these articles, see Publications in http://www.cs.nott.ac.uk/~ixp/.
I would like to thank the following people for fruitful discussions and collaborations.
(Note: these people do not necessarily support anything I have to say.)