I had been faithful to use CodeWorld as the workbench for my team, but to find out that it runs the program by the browser, i.e. all in frontend, no backend.
So comes Hadui - web UI to Haskell programs in backend.
The idea behind Hadui is rather simple, just to use a web browser in place of the traditional terminal based console UI. Therefore, web technologies (HTML5/WebGL) based GUI & Visualization become native for Haskell programs.
And for simplicity, it's achieved by having the web page (i.e. the frontend) keep life-long WebSocket connection with the process run in background (i.e. the backend), and use text packets for comm:
-
in order to control the representation state in browser, json command is sent from the backend Haskell program to web page for execution.
-
in responding to user interactions with the web page, Haskell code is sent from browser to backend process for execution.
This is fundamentally not different than tradition IO approach to implement Terminal/Text UI for a (emulated) terminal , only more flexible as it's inherently easier to extend the json commands (inplace of ANSI Escape sequences ) and Haskell statements (inplace of ASCII control characters ) compared to terminal based interactions via stdio, and not limited to one tty per process - you can have many web pages open to interact with a single process.
And a plus: binary packets/streams through the WebSocket can be used to communicate binary data efficiently between frontend and backend.
With a rather small codebase, and the most extraordinary dependencies being websockets and snap-server , Hadui is no more than a vanilla Haskell program (with rio as the replacement Prelude if you care), actually you can hack it all the way you'd like.
But for productivity, in composing vast Haskell pieces into an interactive context, with fast development iterations in mind, we choose to dynamicly compile & execute a Haskell project underlying. Therefore this pending feature request for interactive frontend support in GHCi , it's not in stock GHC yet, now lives in this experimental GHC branch as time being. Meaning you need a custom built GHC to use Hadui for now.
Fortunately Nix can save our asses in building GHC from source painlessly, at the mere cost of several GBs of disk space and one-shot build time of about one hour each GHC version.
So besides the source available from its github repository, Hadui is only distributed via Nixpkgs.
Mind you that Nix is Linux focused, with decent support for macOS but Windows is not well supported. Much the same Hadui is.
Install Nix if not already.
There're 3 flavors of Hadui project you can choose freely to start with, each with a scaffold template ready. To setup an interactive Haskell project with web UI:
Stack based
curl -L https://github.com/complyue/hadui-demo-stack/archive/master.tar.gz | tar xzf -
mv hadui-demo-stack-master my-awsome-project
cd my-awsome-project
nix-shell --run 'stack build --exec hadui'
Cabal based
curl -L https://github.com/complyue/hadui-demo-cabal/archive/master.tar.gz | tar xzf -
mv hadui-demo-cabal-master my-awsome-project
cd my-awsome-project
nix-shell --run 'cabal v2-build all && hadui'
curl -L https://github.com/complyue/hadui-demo-nix/archive/master.tar.gz | tar xzf -
mv hadui-demo-nix-master my-awsome-project
cd my-awsome-project
nix-shell --run hadui
Hadui is data science oriented, it is not suitable as a general purpose web framework.
Artifacts from the underlying project are exposed to frontend in a flat name space. This is ideal to support analytical workflows, but overly open or even prohibitive to support business workflows.
The mod to add
interactive frontend support
to GHC is very light - simply added :frontend
cmd to allow a
Frontend plugin be used with GHCi.
I would be maintaining custom branches matching the GHC version chosen
by latest
LTS Haskell as well as
Nixpkgs, which is 8.6.5
at time of speaking.
I believe Hadui can be useful in more ways for you and others, e.g. a version of CodeWorld capable to leverage the computing power of a computing center on the cloud.
Data analysts use a browser to submit scripts (in native Haskell, for parameters, simple job control etc.) to trigger number crunching in the backend (a single Haskell process or a swarm of computing nodes), and to see results plotted back to the browser - more windows opened to show Bokeh figures (with Haze as a Hadui overlay package yet under construction).
Programmers have hadui-dev
as the default build tool run an ever going
build task in their VSCode environment
with HIE enabled via
VsCode extension for Haskell
, to develop crunching code in Haskell projects.
Haskell code from Hadui UI runs in the UIO
monad. It's pretty much the
same as RIO
from the rio
library, with few addons like print
/uiLog
, and concrete env
of type
UserInterfaceOutput
. It is essentially ReaderT UserInterfaceOutput IO
,
so you can do (un)lifting within it however you need.
-- | The monad for User Interface Output
-- UIO is output only, conversely to IO (which stands for Input/Output),
-- user inputs shall be facilitated with a registry of 'MVar's,
-- those get filled with 'IoC' from UI widgets.
newtype UIO a = UIO { unUIO :: ReaderT UserInterfaceOutput IO a }
deriving (Functor, Applicative, Monad, MonadIO,
MonadReader UserInterfaceOutput, MonadThrow)
After all, your code in the Haskell project has no necessarity to do with UIO
at all,
print :: Display a => a -> UIO ()
can give you a handful hand to show virtually any value to the log box in UI.
(check out the
Display
typeclass) And you can always do
liftIO
or similar to obtain a value within a do
block as necessary.
And the UIO
module re-exports
RIO
, so you can use it for
Prelude replacement
as well as RIO
.
After started the project you've created from any of the scaffolds as instructed above, open http://localhost:5050
Tip: there's development mode (run
hadui-dev
instead ofhadui
), where you can just refresh the browser page after source modification in the project, the backend process will be restarted, and changed source will be recompiled automatically.
-
you customize front UI for your project, by having a
hadui
folder besideshadui.yaml
under the project root.take for example: https://github.com/complyue/hadui-demo-stack/tree/master/hadui
-
the Rating.hs module is paired with rating.html page to use state in frontend only.
-
the StatefulRating.hs module is paired with stateful-rating.html page to use state in backend.
-
the updateRank js method is shared by above 2 examples to update UI from Haskell code.
-
-
wanna your own front page ?
just create hadui/front.html
under your project root.
all resources under https://github.com/complyue/hadui/tree/master/hadui/web can be preceded by placing a same named file under your project's
hadui
folder. there befront.html
of just symlink todev.html
, with your own front page inplace, you can still access the good old dev page at: http://localhost:5050/dev.html
Setup your VSCode environment with HIE enabled via VsCode extension for Haskell
Just open with VSCode the project you've created from one of the scaffold
templates above, there's already .vscode/tasks.json
from the scaffold with
following contents:
{
"version": "2.0.0",
"presentation": {
"reveal": "always",
"panel": "new"
},
"tasks": [
{
"group": {
"kind": "build",
"isDefault": true
},
"label": "hadui-dev",
"type": "shell",
"command": "cd ${workspaceRoot}; nix-shell --run hadui-dev"
}
]
}
Press F7
(macOS) or Ctrl+Shift+B
(Linux) to start hadui-dev
for the project
coming sooner than later ...