[英]How to call Haskell from Javascript with GHCJS
我一直在玩GHCJS。 FFI可用于从Haskell调用javascript,但我无法弄清楚如何反过来。 假设我在Haskell中编写了一个超级有用的实用函数:
sayHello :: String -> IO ()
sayHello name = print $ "hello, " ++ name
有可能做一些事情,所以我可以从Javascript调用它吗? 我最接近的是注意到h$main(h$main2CMainzimain)
将触发我的Haskell主函数。
这是一种让它发挥作用的方法。 假设我们有一些有用的功能,比如
revString :: String -> String
revString = reverse
somethingUseful :: JSString -> IO JSString
somethingUseful = return . toJSString . revString . fromJSString
为了导出它,我们需要通过GHCJS.Foreign
一个*Callback
函数使其成为回调函数。 但是这些会丢弃返回值,所以我们需要一个将结果放入第二个参数的包装器:
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方面的一些un-wrapper:
function somethingUseful (arg) {x = {}; somethingUseful_(arg, x); return x.ret};
现在我们可以使用我们很好的Haskell实现的函数:
somethingUseful("Hello World!")
"!dlroW olleH"
我在实际应用程序中使用此技巧。 在JsInterface.hs ,其被定义为main-in
所述的executable
在卡瓦尔文件中, main
功能设置全局Java脚本变量incredibleLogic_
,而JavaScript的胶水代码负责包装和拆包的参数。
这是一个示例,演示如何从Javascript调用Haskell函数。 这类似于Joachim提供的示例,但编译并运行最新的ghcjs。
import GHCJS.Marshal(fromJSVal)
import GHCJS.Foreign.Callback (Callback, syncCallback1, OnBlocked(ContinueAsync))
import Data.JSString (JSString, unpack, pack)
import GHCJS.Types (JSVal)
sayHello :: String -> IO ()
sayHello name = print $ "hello, " ++ name
sayHello' :: JSVal -> IO ()
sayHello' jsval = do
Just str <- fromJSVal jsval
sayHello $ unpack str
foreign import javascript unsafe "js_callback_ = $1"
set_callback :: Callback a -> IO ()
foreign import javascript unsafe "js_callback_($1)"
test_callback :: JSString -> IO ()
main = do
callback <- syncCallback1 ContinueAsync sayHello'
set_callback callback
test_callback $ pack "world"
测试通过从Haskell调用Javascript代码然后调用回Haskell来工作。 变量“js_callback_”在Javascript中可用作带有一个字符串参数的函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.