Haskell 在反射dom中,如何将值从动态传递到外部javascript函数(FFI)

Haskell 在反射dom中,如何将值从动态传递到外部javascript函数(FFI),haskell,ffi,reflex,Haskell,Ffi,Reflex,我对Haskell和dom还不熟悉,但我很喜欢这门语言。我一直在学习,这对我很有帮助 我目前正在尝试创建一个函数,该函数接受动态,并创建一个元素,每次动态中的值更改时都调用FFI函数。这是我试图做的一个简化版本 {-# LANGUAGE OverloadedStrings #-} import Data.Text as T import qualified GHCJS.DOM.Types as GDT import GHCJS.Types import Reflex.Dom foreign i

我对Haskell和dom还不熟悉,但我很喜欢这门语言。我一直在学习,这对我很有帮助

我目前正在尝试创建一个函数,该函数接受动态,并创建一个元素,每次动态中的值更改时都调用FFI函数。这是我试图做的一个简化版本

{-# LANGUAGE OverloadedStrings #-}
import Data.Text as T
import qualified GHCJS.DOM.Types as GDT
import GHCJS.Types
import Reflex.Dom

foreign import javascript safe
  "$1.value = $2"
  testSet :: JSVal -> JSVal -> IO()

testTB :: DomBuilder t m => Dynamic t T.Text -> m ()
testTB dt = do
  (e, _) <- elAttr' "input" ("type" =: "text") blank
  bob <- (testSet (GDT.pToJSVal e) . GDT.pToJSVal) <$> dt
  return ()

main = mainWidget $ testTB $ constDyn "Hello World!"
{-#语言重载字符串}
导入数据。文本为T
将符合条件的GHCJS.DOM.Types导入为GDT
导入GHCJS。类型
导入反射.Dom
国外进口javascript安全
“$1.value=$2”
testSet::JSVal->JSVal->IO()
testTB::DomBuilder t m=>动态t.Text->m()
testTB dt=do
(e,∗)*)。
DOMTM=>
动态t文本->m()
在反射画布上。hs:11:11
预期类型:m(IO())
实际类型:动态t(IO())
•在“do”块的stmt中:

bob函数
performEvent\uu
将强制执行javascript函数,但
performEvent\u
需要
事件t(WidgetHost m())
,并且,正如错误消息所指出的,您得到了
动态t(IO())

您可以使用
updated
将您的
Dynamic t(IO())
转换为
Event t(IO())
,并且可以使用
fmap liftIO
事件中的
IO()
更改为
WidgetHost m()
留下
事件t(WidgetHost m())
您可以将其传递到
performEvent\u

这是经过这些修改的代码。我删除了
testSet
的第一个参数和
testTB
中的元素创建,因为它们与问题/解决方案无关。我还添加了一些额外的类型声明。这些不是必需的,但可能会使事情更清楚

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Text as T (Text)
import qualified GHCJS.DOM.Types as GDT (pToJSVal)
import GHCJS.Types (JSVal)
import Reflex.Dom
import Control.Monad.Trans (liftIO)

foreign import javascript safe
  "console.log $1"
  testSet :: JSVal -> IO()

testTB :: forall t m.  MonadWidget t m => Dynamic t T.Text -> m ()
testTB dt = do 
    let bob :: Dynamic t (IO ())
        bob = (testSet.(GDT.pToJSVal)) <$> dt  

        bobIOEvent :: Event t (IO ())
        bobIOEvent = updated bob

        bobWidgetHostEvent :: Event t (WidgetHost m ())
        bobWidgetHostEvent = fmap liftIO bobIOEvent

    performEvent_ bobWidgetHostEvent

main = mainWidget $ do
    ti <- textInput def 
    let dt = value ti
    testTB dt
{-#语言重载字符串}
{-#语言范围类型变量#-}
导入数据。文本作为T(文本)
将符合条件的GHCJS.DOM.Types导入为GDT(pToJSVal)
导入GHCJS.Types(JSVal)
导入反射.Dom
进口控制单体转运(liftIO)
国外进口javascript安全
“console.log$1”
testSet::JSVal->IO()
testTB::对于所有t m。MonadWidget t m=>动态t.Text->m()
testTB dt=do
让bob::动态t(IO())
bob=(testSet.(GDT.pToJSVal))dt
bobIOEvent::事件t(IO())
bobIOEvent=已更新的bob
bobWidgetHostEvent::事件t(WidgetHost m())
bobWidgetHostEvent=fmap liftIO bobIOEvent
performEvent_ubWidgetHostEvent
main=mainWidget$do

i你试过
liftIO
ing吗?我的意思是
liftIO(testSet(GDTpToJSVal e).GDT.pToJSVal)=您选择省略大部分错误,这通常是非常全面的信息。了解错误可能会告诉您如何修复它;一个好的答案会给出修正并解释错误(教人钓鱼等等)。@epsilonhalbe刚刚尝试了liftM和liftIO的一些变体,但似乎无法使其工作。@user2407038刚刚添加了完整的错误消息。您无法从动态monad中获取t.Text值并将其直接用作testSet函数的参数。您必须在monad中以应用程序模式运行testSet函数。类似于
testSet ptrToHTMLControl ptrToText
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Text as T (Text)
import qualified GHCJS.DOM.Types as GDT (pToJSVal)
import GHCJS.Types (JSVal)
import Reflex.Dom
import Control.Monad.Trans (liftIO)

foreign import javascript safe
  "console.log $1"
  testSet :: JSVal -> IO()

testTB :: forall t m.  MonadWidget t m => Dynamic t T.Text -> m ()
testTB dt = do 
    let bob :: Dynamic t (IO ())
        bob = (testSet.(GDT.pToJSVal)) <$> dt  

        bobIOEvent :: Event t (IO ())
        bobIOEvent = updated bob

        bobWidgetHostEvent :: Event t (WidgetHost m ())
        bobWidgetHostEvent = fmap liftIO bobIOEvent

    performEvent_ bobWidgetHostEvent

main = mainWidget $ do
    ti <- textInput def 
    let dt = value ti
    testTB dt