簡體   English   中英

如何使用GHCJS從Javascript調用Haskell

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM