Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用GHCJS从Javascript调用Haskell_Haskell_Ghcjs - Fatal编程技术网

如何使用GHCJS从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函数。这里有一种方法可以让它工作。假

我一直在和GHCJ玩。FFI可以用来从Haskell调用javascript,但我不知道如何反过来。假设我在Haskell中编写了一个非常有用的实用函数:

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"