GithubHelp home page GithubHelp logo

meteogrid / ghcjs-commonjs Goto Github PK

View Code? Open in Web Editor NEW

This project forked from konn/ghcjs-commonjs

0.0 5.0 0.0 6.31 MB

Seamless calls of Haskell code from JavaScript modules

License: MIT License

Makefile 5.39% Haskell 59.88% JavaScript 34.18% Shell 0.24% HTML 0.32%

ghcjs-commonjs's Introduction

ghcjs-commonjs

CircleCI Build Status


ghcjs-commonjs is a work-in-progress collection of little hacks to make GHCJS generated JavaScript and CommonJS integration less troublesome.

This hasn't been tested in production yet, so try the examples and report any issues that you have

We provide the following tools:

  • ghcjs-require - Calling Haskell from Node.js and CommonJS
  • ghcjs-commonjs - Exposing Haskell to be called from CommonJS
  • ghcjs-register - require('./MyHaskellModule.hs')
  • ghcjs-loader - A webpack loader for GHCJS

See the examples! You can run them all with make.

The modules have not been published to Hackage or NPM yet, but should be installable from git or the filesystem.

Utilities for loading GHCJS .jsexes from CommonJS land.

Callling Haskell from JavaScript

This is main.js:

const ghcjsRequire = require('ghcjs-require');
const Main = ghcjsRequire(module, './Main.jsexe');
// ^^ This is a function that boots the Haskell RTS
Main(({wrapped}) => { // <- This callback is executed after the RTS is loaded
  wrapped.someFunction().then(() => console.log('someFunction is over'));
  // ^^ This function was generated, it'll call Haskell code asynchronously and
  //    return a promise to the result

  wrapped.hello('John').then((ret) => console.log(ret));
  // ^^ Arguments and return values are automatically (de-)serialized we can use
  //    multi-arg functions, IO actions and pure values
});

The Haskell side of things for exposing code to ghcjs-require.

Exposing Haskell to JavaScript

This is Main.hs:

import Control.Concurrent (threadDelay)
import GHCJS.CommonJS (exportMain, exports)
someFunction = do
    putStrLn "Waiting for a second"
    threadDelay (1000 * 1000)
    putStrLn "Done!"
main = exportMain [ "someFunction" `exports` someFunction
                  , "hello" `exports` \name -> "Hello " ++ name
                  ]

On the likes of coffee-script/register or babel-register:

require('ghcjs-register');
const Main = require('./Main.hs');

This is a webpack loader for GHCJS. See the examples.

How does it work?

Following the guidelines set on "Writing Atom plugins in Haskell using GHCJS", this project exports two main libraries: ghcjs-require is a JavaScript library for wrapping GHCJS output in a CommonJS module and ghcjs-commonjs uses this library's semantics to expose Haskell values to the JavaScript world.

Other than wrapping GHCJS' output in a module, ghcjs-require injects an EventEmitter instance, which then serves as a message bus between Haskell and JavaScript.

The ghcjs-commonjs package uses this bus through the exports and exportMain primitives, listening for events on the emitter and executing functions as requested.

The JavaScript side does some more wrapping to hide the event calling and callbacks from the user, providing a promise based API.

The type of exportMain is:

exportMain :: (Foldable t) => t (String, CommonJSExport) -> IO ()

So we can receive any Foldable instance of tuples of the export name to a CommonJSExport. A CommonJSExport is:

type CommonJSExport = [JSVal] -> IO [JSVal]

So a function that can take an arbitrary amount of arguments and return an arbitrary amount of results

We then use an exports primitive:

exports :: ToCommonJSExport (String, e) => String -> e -> (String, CommonJSExport)

This uses a type-class ToCommonJSExport, which knows how to convert certain Haskell values to CommonJSExports, which then can be trivially wrapped onto JavaScript functions.

To interact with the EventEmitter we use an internal, work-in-progress, wrapper exposed in JavaScript.EventEmitter and a global variable which we get from ghcjs-register.

This should be enough for Haskell/Node.js interop. For browsers, the webpack integration should offer a way of using Haskell code in a state-of-the-art JavaScript set-up.

All in all, it needs testing and examples that show that it adds or doesn't add value, but I recommend you clone the repository and try the example code out.

License

All code under this repository is licensed under the MIT license.

ghcjs-commonjs's People

Contributors

albertov avatar yamadapc avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.