如何使用GHCJS从Javascript调用Haskell
我一直在和GHCJ玩。FFI可以用来从Haskell调用javascript,但我不知道如何反过来。假设我在Haskell中编写了一个非常有用的实用函数:如何使用GHCJS从Javascript调用Haskell,haskell,ghcjs,Haskell,Ghcjs,我一直在和GHCJ玩。FFI可以用来从Haskell调用javascript,但我不知道如何反过来。假设我在Haskell中编写了一个非常有用的实用函数: sayHello :: String -> IO () sayHello name = print $ "hello, " ++ name 是否可以做一些事情,以便我可以从Javascript调用它?我最近注意到,h$main(h$main2CMainzimain)将触发我的Haskell main函数。这里有一种方法可以让它工作。假
sayHello :: String -> IO ()
sayHello name = print $ "hello, " ++ name
是否可以做一些事情,以便我可以从Javascript调用它?我最近注意到,
h$main(h$main2CMainzimain)
将触发我的Haskell main函数。这里有一种方法可以让它工作。假设我们有一些有用的函数,比如
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
最后,我们在JS端需要一个小的un包装器:
function somethingUseful (arg) {x = {}; somethingUseful_(arg, x); return x.ret};
现在我们可以使用nice HASKEL实现的函数:
somethingUseful("Hello World!")
"!dlroW olleH"
我在一个真实的应用程序中使用这个技巧。在中,定义为中的可执行文件的
中的main
,main
函数设置全局java脚本变量incredibleLogic
,同时负责打包和解包参数。下面的示例演示如何从Javascript调用Haskell函数。这与Joachim提供的示例类似,但使用最新的GHCJ编译和运行
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"
导入GHCJS.Marshal(fromJSVal)
导入GHCJS.Foreign.Callback(Callback、syncCallback1、OnBlocked(ContinueAsync))
导入Data.JSString(JSString、解包、打包)
导入GHCJS.Types(JSVal)
sayHello::String->IO()
sayHello name=print$“hello,++name
sayHello':JSVal->IO()
sayHello'jsval=do
只是strio()
国外进口javascript不安全“js_回调(1美元)”
test_回调::JSString->IO()
main=do
回调如果仍然适用,它将不会很好-如果你想要这个方向可能是一个更好的选择如果情况变得更糟,你可以潜在地使用FFI来解决问题。因此,如果您有var haskell={},export=funcon(name,val){haskell[name]=val;}
然后通过FFI将export
导入Haskell,export“sayHello”sayHello
应该潜在地将Haskell.sayHello
设置为任何函数,而不让奇怪的h$main()
变量乱扔东西。你在github的某个地方碰巧有这个吗?所以我可以用GHCJS编译它?谢谢,我看了一下。这里的返回值是多少?incredibleLogic\uuu
从哪里来?很抱歉这么简短的评论,我当时在用手机。我现在在答案中详细阐述了它——它有帮助吗?那么,在main.hs
中调用js\u set\u somethingUseful
会导致somethingUseful\u
出现在Javascript全局命名空间中?我理解正确吗?您使用了哪个版本的GHCJS?我遇到以下错误:模块“GHCJS.Marshal”不导出“fromJSVal”
,模块“GHCJS.Types”在我尝试编译上述代码时不导出“JSVal”
。我使用的是ghcjs-0.2.0.20151001\u ghc-7.10.2
。dave@6d322ff6c63d:~$ghcjs——版本光荣的格拉斯哥哈斯克尔JavaScript编译系统,版本0.2.0(GHC 7.10.3),非常奇怪。如果我们都有GHCJS-0.2.0,有什么想法会导致我们有不同的模块吗?不是随便说说。我可以在几个小时内对此进行更详细的研究。上面的示例在github中提供:。我添加了一个分支nodejs,它编译成在node.js下运行的代码。此分支包含一个haskell->javascript->haskell调用序列,其中javascript位于仅javascript的源文件中,Main.jsexe/tc.js
,对haskell的回调通过js\u callback
变量完成。在all.js
之外访问它不需要导出js\u callback\ucode>。
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"