2015-04-30 25 views
19

GHCJS ile oynuyorum. FFI, Haskell'den javascript'i çağırmak için kullanılabilir, ancak diğer yoldan nasıl geçeceğimi anlayamıyorum.GHCJS ile Haskell nasıl çağrılır?

sayHello :: String -> IO() 
sayHello name = print $ "hello, " ++ name 

yüzden Javascript diyebiliriz mümkün bir şey yapmak mı: Ben Haskell yazdığı süper kullanışlı yarar işlevi vardı ki? Aldığım en yakın nokta, h$main(h$main2CMainzimain)'un Haskell ana işlevimi tetikleyeceğini fark ediyor.

+1

[bu] (http://weblog.luite.com/wordpress/?p=14) hala geçerliyse bu hoş olmaz - eğer bu yönü istiyorsanız [fay] (https://github.com/ kötü kötü potansiyel sorunu çözmek için FFI kullanabilirsiniz gelirse faylang/fay/wiki/çağrılması-Fay-den-JavaScript) daha iyi bir seçim – Carsten

+0

olabilir. Yani eğer var haskell = {}, export = functon (isim, val) {haskell [name] = val; }; 'Ve ardından' getirmek FFI aracılığıyla Haskell içine export', 'ihracat "sayHello" sayHello' potansiyel garip' h $ main olmadan fonksiyonu ne olursa olsun olmak 'haskell.sayHello', belirlesin()' herşeyi çöp değişkenler. –

cevap

10

İşte bunu yapmanın bir yolu. Bu ihraç etmek amacıyla

revString :: String -> String 
revString = reverse 

somethingUseful :: JSString -> IO JSString 
somethingUseful = return . toJSString . revString . fromJSString 

gibi, biz GHCJS.Foreign içinde *Callback işlevlerinden biri aracılığıyla bunu bir geri arama yapmak gerekir, biz bazı yararlı fonksiyonu var varsayalım. Ancak bu dönüş değeri göz ardı ediyorum, bu yüzden ikinci bir argüman haline sonucu koyar bir sarmalayıcı gerekir:

returnViaArgument :: (JSRef a -> IO (JSRef b)) -> JSRef a -> JSRef c -> IO() 
returnViaArgument f arg retObj = do 
    r <- f arg 
    setProp "ret" r retObj 

Benim main geri çağırma işlevi oluşturur ve JavaScript küresel bir şeyden olarak kaydeder:

foreign import javascript unsafe "somethingUseful_ = $1" 
    js_set_somethingUseful :: JSFun a -> IO() 

main = do 
    callback <- syncCallback2 NeverRetain False (returnViaArgument somethingUseful) 
    js_set_somethingUseful callback 

Son olarak, JS tarafta biraz un-sarmalayıcı gerekir:

function somethingUseful (arg) {x = {}; somethingUseful_(arg, x); return x.ret}; 

ve şimdi bizim güzel Haskell-uygulanan işlevi kullanabilirsiniz:

somethingUseful("Hello World!") 
"!dlroW olleH" 

Bu hileyi gerçek dünyadaki bir uygulamada kullanıyorum. Cabal file'da executable'un main-in10 olarak tanımlanan JsInterface.hs'da, main işlevi incredibleLogic_ global java komut değişkeni ayarlarken, JavaScript glue code parametreleri paketlemenin ve paketlerinin açılmasının üstesinden gelir.

+0

Çok teşekkürler Joachim! – jhegedus

+0

Github'da bu bir yer var mı? Bu yüzden GHCJS kullanarak derleyebilir miyim? – jhegedus

+0

kitaplık olarak ama https://github.com/nomeata/incredible –

6

Burada, Javascript'ten bir Haskell işlevinin nasıl çağrılacağını gösteren bir örnek verilmiştir. Bu, Joachim tarafından sağlanan örneğe benzer, ancak en yeni ghcjs ile derler ve çalışır.

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" 

Test, Haskell'den Haskell'e geri çağrı yapan Javascript koduna çağrı yaparak çalışır. "Js_callback_" değişkeni, bir dizge argümanını alan bir işlev olarak kullanmak için Javascript içinde kullanılabilir hale gelir.

+0

Hangi GHCJS sürümünü kullandınız? Bu hataları alıyorum: Modül ‘GHCJS.Marshal’, JJSVal’den, dışa aktarmıyor, “Yukarıdaki kodları derlemeye çalıştığımda Module JSVal’in Modülü‘ GHCJS.Types ’dışa aktarmıyor. Ben ghcjs-0.2.0.20151001_ghc-7.10.2 kullanıyorum. – Wizek

+0

dave @ 6d322ff6c63d: ~ $ ghcjs --version JavaScript için Glorious Glasgow Haskell Derleme Sistemi, sürüm 0.2.0 (GHC 7.10.3) –

+0

Bu çok meraklı. İkimiz de GHCJS-0.2.0'ımız varsa, farklı modüllere sahip olmamıza ne gibi bir fikir verebiliriz? – Wizek