How to call Haskell from Javascript with GHCJS

Gareth Charnock

I've been playing about with GHCJS. The FFI can be used to call javascript from Haskell but I can't figure out how do go the other way round. Say I had a super useful utility function I wrote in Haskell:

sayHello :: String -> IO ()
sayHello name = print $ "hello, " ++ name

Is it possible do something so I could call it from Javascript? The closest I've got is noticing that h$main(h$main2CMainzimain) will trigger my Haskell main function.

Joachim Breitner

Here is a way to make it work. Assume we have some useful function, like

revString :: String -> String
revString = reverse

somethingUseful :: JSString -> IO JSString
somethingUseful = return . toJSString . revString  . fromJSString

In order to export that, we need to make it a callback via one of the *Callback functions in GHCJS.Foreign. But these would discard the return value, so we need a wrapper that puts the result into a second argument:

returnViaArgument :: (JSRef a -> IO (JSRef b)) -> JSRef a -> JSRef c -> IO ()
returnViaArgument f arg retObj = do
    r <- f arg
    setProp "ret" r retObj

My main function creates the callback, and saves it as something that’s global to JavaScript:

foreign import javascript unsafe "somethingUseful_ = $1"
    js_set_somethingUseful :: JSFun a -> IO ()

main = do
    callback <- syncCallback2 NeverRetain False (returnViaArgument somethingUseful)
    js_set_somethingUseful callback

Finally, we need a little un-wrapper on the JS side:

function somethingUseful (arg) {x = {}; somethingUseful_(arg, x); return x.ret};

and now we can use our nice Haskell-implemented function:

somethingUseful("Hello World!")
"!dlroW olleH"

I am using this trick in a real-world application. In JsInterface.hs, which is defined as main-in of the executable in the Cabal file, the main function sets the global java script variable incredibleLogic_, while the JavaScript glue code takes care of packing and unpacking the parameters.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

How to call Java function dynamically from Javascript?

From Javascript

How to call javascript function from <script> tag?

From Javascript

How to call javascript from a href?

From Javascript

How to call a JavaScript function from PHP?

From Java

How to call javascript from Android?

From Dev

How to call a JavaScript function from within Selenium?

From Dev

How to call Javascript from Razor View

From Dev

How do you convert from an Unboxed Vector to a JS TypedArray on GHCJS?

From Dev

How to call JavaScript libraries from TypeScript project?

From Dev

How to call Python functions from JavaScript in Django?

From Dev

How do immutable languages like ClojureScript, Elm, PureScript, GHCJS compile to mutable javascript?

From Dev

How to call constructor from Template Haskell

From Dev

How to call a shell command from JavaScript JXA?

From Dev

How to call javascript from swift

From Dev

how to call javascript function from SmartGWT function

From Dev

Call a DLL from Haskell

From Dev

How to call a Dart function from JavaScript

From Dev

How to call CSS from JavaScript

From Dev

How to call Pyramid server from JavaScript

From Dev

How to call php file from javascript?

From Dev

How to call JavaScript from Java

From Dev

how to call javascript function from Android

From Dev

Is it possible GHCJS to reuse code generated by Template Haskell

From Dev

How to call a native view method from JavaScript

From Dev

How to call Ajax from Javascript function

From Dev

How to open new winform from javascript call?

From Dev

How to Call C++ Setters & Getters from Haskell

From Dev

How to call brython/python from javascript?

From Dev

How to install ghcjs 8.8 or 8.10?

Related Related

HotTag

Archive