我是Haskell和反射的新手,但非常喜欢这种语言。我一直在使用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()但无法弄明白。这样做的最佳做法是什么?
答案 0 :(得分:2)
函数performEvent_
将强制执行javascript函数,但performEvent_
需要Event t (WidgetHost m ())
,并且正如错误消息所指出的那样,您已获得Dynamic t (IO ())
}。
您可以使用updated
将Dynamic t (IO ())
转换为Event t (IO ())
,然后使用fmap liftIO
更改IO ()
中的Event
到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