An open API service indexing awesome lists of open source software.

https://github.com/thblt/hsbang

Run Haskell programs as if they were scripts, without the interpreter overhead
https://github.com/thblt/hsbang

Last synced: 8 months ago
JSON representation

Run Haskell programs as if they were scripts, without the interpreter overhead

Awesome Lists containing this project

README

          

#+TITLE: hsbang

Scripting in Haskell is difficult because of two issues: compatibility
and performance. [[https://docs.haskellstack.org/en/stable/README/][Stack]] solves the compatibility issue by behaving as
a [[https://docs.haskellstack.org/en/stable/GUIDE/#script-interpreter][script interpreter]], but performance so far is horrible: on my
machine, a /Hello, world!/ takes more than 1s to run.

=hsbang= is a shebang pseudo-interpreter for Haskell programs using
Stack, but instead of actually running the script on an interpreter,
it calls =stack= and =ghc= to compile it to native code, and caches the
resulting binary. If the same script is called again, the cached
binary is run. Performance is incomparable:

#+BEGIN_EXAMPLE
$ ./hello.stack
Hello, world!
/hello.stack 1,04s user 0,17s system 101% cpu 1,191 total

$ ./hello.hsbang
Hello, world!
/hello.hsbang 0,01s user 0,01s system 100% cpu 0,027 total
#+END_EXAMPLE

Yes, that's 44 times faster.

* Usage

=hsbang= is a shebang interpreter. To use it to write an Haskell script, all you have to do is:

#+BEGIN_SRC haskell
#!/usr/bin/env hsbang
-- stack --resolver=lts-11.7 --package ncurses

import UI.NCurses

main :: IO ()
main = runCurses $ do
setEcho False
w <- defaultWindow
updateWindow w $ do
moveCursor 1 10
drawString "Hello world!"
moveCursor 3 10
drawString "(press q to quit)"
moveCursor 0 0
render
waitFor w (\ev -> ev == EventCharacter 'q' || ev == EventCharacter 'Q')

waitFor :: Window -> (Event -> Bool) -> Curses ()
waitFor w p = loop where
loop = do
ev <- getEvent w Nothing
case ev of
Nothing -> loop
Just ev' -> if p ev' then return () else loop
#+END_SRC