{"id":18391310,"url":"https://github.com/thblt/hsbang","last_synced_at":"2025-10-16T14:04:17.837Z","repository":{"id":68387325,"uuid":"132015811","full_name":"thblt/hsbang","owner":"thblt","description":"Run Haskell programs as if they were scripts, without the interpreter overhead","archived":false,"fork":false,"pushed_at":"2018-05-03T17:20:36.000Z","size":16,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-16T01:25:26.891Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thblt.png","metadata":{"files":{"readme":"README.org","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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-03T15:34:49.000Z","updated_at":"2018-05-03T17:20:37.000Z","dependencies_parsed_at":"2023-02-27T21:45:52.643Z","dependency_job_id":null,"html_url":"https://github.com/thblt/hsbang","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Fhsbang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Fhsbang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Fhsbang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thblt%2Fhsbang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thblt","download_url":"https://codeload.github.com/thblt/hsbang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248548343,"owners_count":21122679,"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":[],"created_at":"2024-11-06T01:51:27.461Z","updated_at":"2025-10-16T14:04:17.733Z","avatar_url":"https://github.com/thblt.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+TITLE: hsbang\n\nScripting in Haskell is difficult because of two issues: compatibility\nand performance.  [[https://docs.haskellstack.org/en/stable/README/][Stack]] solves the compatibility issue by behaving as\na [[https://docs.haskellstack.org/en/stable/GUIDE/#script-interpreter][script interpreter]], but performance so far is horrible: on my\nmachine, a /Hello, world!/ takes more than 1s to run.\n\n=hsbang= is a shebang pseudo-interpreter for Haskell programs using\nStack, but instead of actually running the script on an interpreter,\nit calls =stack= and =ghc= to compile it to native code, and caches the\nresulting binary.  If the same script is called again, the cached\nbinary is run.  Performance is incomparable:\n\n#+BEGIN_EXAMPLE\n$ ./hello.stack\nHello, world!\n/hello.stack  1,04s user 0,17s system 101% cpu 1,191 total\n\n$ ./hello.hsbang\nHello, world!\n/hello.hsbang  0,01s user 0,01s system 100% cpu 0,027 total\n#+END_EXAMPLE\n\nYes, that's 44 times faster.\n\n* Usage\n\n=hsbang= is a shebang interpreter.  To use it to write an Haskell script, all you have to do is:\n\n#+BEGIN_SRC haskell\n  #!/usr/bin/env hsbang\n  -- stack --resolver=lts-11.7 --package ncurses\n\n  import UI.NCurses\n\n  main :: IO ()\n  main = runCurses $ do\n      setEcho False\n      w \u003c- defaultWindow\n      updateWindow w $ do\n          moveCursor 1 10\n          drawString \"Hello world!\"\n          moveCursor 3 10\n          drawString \"(press q to quit)\"\n          moveCursor 0 0\n      render\n      waitFor w (\\ev -\u003e ev == EventCharacter 'q' || ev == EventCharacter 'Q')\n\n  waitFor :: Window -\u003e (Event -\u003e Bool) -\u003e Curses ()\n  waitFor w p = loop where\n      loop = do\n          ev \u003c- getEvent w Nothing\n          case ev of\n              Nothing -\u003e loop\n              Just ev' -\u003e if p ev' then return () else loop\n#+END_SRC\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthblt%2Fhsbang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthblt%2Fhsbang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthblt%2Fhsbang/lists"}