gpt4 book ai didi

haskell - 在reflex-dom中,如何将值从动态传递到外部javascript函数(FFI)

转载 作者:行者123 更新时间:2023-12-02 16:12:24 25 4
gpt4 key购买 nike

我是 Haskell 和 reflex-dom 的新手,但真的很喜欢这门语言。我一直在使用https://github.com/hansroland/reflex-dom-inbits/blob/master/tutorial.md学习了,很有帮助。

我目前正在尝试创建一个函数,该函数接受动态并创建一个元素,并在每次动态中的值发生变化时调用 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!"

这会导致编译时错误:

reflex-canvas.hs:14:10: error:
• Couldn't match type ‘m’ with ‘Dynamic t’
‘m’ is a rigid type variable bound by
the type signature for:
testTB :: forall t (m :: * -> *).
DomBuilder t m =>
Dynamic t Text -> m ()
at reflex-canvas.hs:11:11
Expected type: m (IO ())
Actual type: Dynamic t (IO ())
• In a stmt of a 'do' block:
bob <- (testSet (GDT.pToJSVal e) . GDT.pToJSVal) <$> dt
In the expression:
do { (e, _) <- elAttr' "input" ("type" =: "text") blank;
bob <- (testSet (GDT.pToJSVal e) . GDT.pToJSVal) <$> dt;
return () }
In an equation for ‘testTB’:
testTB dt
= do { (e, _) <- elAttr' "input" ("type" =: "text") blank;
bob <- (testSet (GDT.pToJSVal e) . GDT.pToJSVal) <$> dt;
return () }
• Relevant bindings include
e :: Element EventResult (DomBuilderSpace m) t
(bound at reflex-canvas.hs:13:4)
dt :: Dynamic t Text (bound at reflex-canvas.hs:12:8)
testTB :: Dynamic t Text -> m () (bound at reflex-canvas.hs:12:1)

我尝试了各种方法将 Dynamic 转换为 m() 但无法弄清楚。这样做的最佳实践是什么?

最佳答案

函数 performEvent_ 将强制执行 JavaScript 函数,但 performEvent_ 需要一个 Event t (WidgetHost m ()) 并且,作为错误消息指出,您有一个Dynamic t (IO ())

您可以使用updatedDynamic t (IO ())转换为Event t (IO ()),然后您可以使用 fmap liftIOEvent 中的 IO () 更改为 WidgetHost m () 留下 Event t (WidgetHost m ()),您可以将其传递给 performEvent_

这是经过这些修改的代码。我删除了 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

关于haskell - 在reflex-dom中,如何将值从动态传递到外部javascript函数(FFI),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47491599/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com