如何从Javascript与GHCJS调用Haskell [英] How to call Haskell from Javascript with GHCJS

查看:148
本文介绍了如何从Javascript与GHCJS调用Haskell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在玩GHCJS。 FFI可以用来从Haskell调用JavaScript,但我无法弄清楚如何做到相反。假设我有一个超级有用的实用函数,我在Haskell中写道:

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

可能做些什么,所以我可以从Javascript调用它?最近我注意到 h $ main(h $ main2CMainzimain)会触发我的Haskell主函数。

解决方案

这是一种使其工作的方法。假设我们有一些有用的函数,比如

  revString :: String  - >字符串
revString =反向

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

为了导出,我们需要通过 *回调函数在 GHCJS.Foreign 中。但是这些会丢弃返回值,所以我们需要一个将结果放入第二个参数的包装:

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

我的 main 函数创建回调函数,并将其保存为JavaScript的全局函数:

  foreign import javascript unsafesomethingUseful_ = $ 1
js_set_somethingUseful :: JSFun a - > IO()

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

最后,我们需要在JS方面稍微解包一下:

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

现在我们可以使用我们很好的Haskell实现的函数:

  somethingUseful(Hello World!)
!dlroW olleH

我在真实世界的应用程序中使用这个技巧。在 JsInterface.hs 中,它定义为<$ 可执行文件的c $ c> main-in /8fa98e59a7b4414d0a78d2e327394cee9a174591/logic/incredible-logic.cabalrel =noreferrer> Cabal file main 函数设置全局Java脚本变量 incredibleLogic _ ,而 JavaScript胶合代码负责打包和解包参数。


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.

解决方案

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.

这篇关于如何从Javascript与GHCJS调用Haskell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆