这是使其工作的一种方法。假设我们有一些有用的功能,比如
revString :: String -> String
revString = reverse
somethingUseful :: JSString -> IO JSString
somethingUseful = return . toJSString . revString . fromJSString
为了导出它,我们需要通过*Callback
. GHCJS.Foreign
但是这些会丢弃返回值,所以我们需要一个将结果放入第二个参数的包装器:
returnViaArgument :: (JSRef a -> IO (JSRef b)) -> JSRef a -> JSRef c -> IO ()
returnViaArgument f arg retObj = do
r <- f arg
setProp "ret" r retObj
我的main
函数创建回调,并将其保存为 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
最后,我们需要在 JS 端进行一些解包:
function somethingUseful (arg) {x = {}; somethingUseful_(arg, x); return x.ret};
现在我们可以使用我们很好的 Haskell 实现的函数了:
somethingUseful("Hello World!")
"!dlroW olleH"
我在现实世界的应用程序中使用了这个技巧。在Cabal 文件中定义的JsInterface.hs中,该函数设置全局 java 脚本变量,而JavaScript 胶水代码负责打包和解包参数。main-in
executable
main
incredibleLogic_