我想创建一个Behavior t a来自一个IO a预期的语义,每次行为是sampled 时都会运行IO动作:
{- language FlexibleContexts #-}
import Reflex.Dom
import Control.Monad.Trans
onDemand :: (MonadWidget t m, MonadIO (PullM t)) => IO a -> m (Behavior t a)
Run Code Online (Sandbox Code Playgroud)
我希望我可以只执行这样做measurement的pull:
onDemand measure = return $ pull (liftIO measure)
Run Code Online (Sandbox Code Playgroud)
但是,在Behavior初始化之后,结果永远不会改变measure.
我可以想到的解决方法是创建一个Behavior"频繁"更改的虚拟对象,然后创建一个假依赖:
import Data.Time.Clock as Time
hold_ :: (MonadHold t m, Reflex t) => Event t a -> m (Behavior t ())
hold_ = hold () …Run Code Online (Sandbox Code Playgroud) 我想执行一个基本的Ajax请求,就是这样.
我reflex用于前端和Scotty后端.Firefox Web控制台告诉我请求是成功的,我在那里看到了预期的结果.但网站切换Just "default"到Nothing而不是Just "success!".
这是一个完整的最小例子:
import Reflex (holdDyn)
import Reflex.Dom (button, el, mainWidget, display)
import Reflex.Dom.Xhr (performRequestAsync, xhrRequest, decodeXhrResponse)
import Reflex.Class (tag, constant)
import Data.Default (def)
main :: IO ()
main = do
mainWidget $ el "div" $ do
buttonEvent <- button "click me"
let defaultReq = xhrRequest "GET" "mystring" def --served by Scotty
asyncEvent <- performRequestAsync (tag (constant defaultReq) buttonEvent)
buttonDyn <- holdDyn (Just "default") $ fmap decodeXhrResponse …Run Code Online (Sandbox Code Playgroud) 使用Reflex-DOM,Event t ()当浏览器准备好绘制下一帧时,即当requestAnimationFrame发生火灾时,我想激发它.我试过这样的:
{-# LANGUAGE RecursiveDo, TypeFamilies #-}
import Reflex.Dom
import Reflex.Host.Class
import GHCJS.DOM (currentWindow)
import GHCJS.DOM.Window as Window
import GHCJS.DOM.Types (RequestAnimationFrameCallback(..))
import GHCJS.Foreign.Callback
import Control.Monad
import Control.Monad.IO.Class
refresh win = do
(event, ref) <- newEventWithTriggerRef
postGui <- askPostGui
rec cb <- liftIO $ asyncCallback1 $ \_timestamp -> do
scheduleNext
putStrLn "about to fire the event"
postGui $ void $ fireEventRef ref ()
putStrLn "event fired"
let scheduleNext = Window.requestAnimationFrame win $ Just $ RequestAnimationFrameCallback cb …Run Code Online (Sandbox Code Playgroud) 我正在构建一种向用户显示对话框的方法.
data DialogConfig t m b e =
DialogConfig { _dialogConfig_title :: Dynamic t T.Text
, _dialogConfig_content :: b -> m (Dynamic t (Maybe b))
, _dialogConfig_footer :: Dynamic t (Maybe b) -> m (Event t e)
}
dialog :: MonadWidget t m =>
DialogConfig t m b e -> Event t b -> m (Event t (DialogEvent e))
Run Code Online (Sandbox Code Playgroud)
我想用某种形式的"默认"实例的初始化DialogConfig的dialog功能,这样我就可以使用它作为如defaultConfig{_dialogConfig_content=content}.但是,我正在与类型推理作斗争.这有效:
confirmDialog :: forall t m. MonadWidget t m =>
T.Text -> Event t T.Text …Run Code Online (Sandbox Code Playgroud) 我发现自己想要一个带有签名的函数:
-- VtyWidget is from https://github.com/reflex-frp/reflex-vty
now :: a -> VtyWidget t m (Event t a)
Run Code Online (Sandbox Code Playgroud)
对于一些m. 此函数将接受一个元素并生成一个小部件,该小部件立即触发一次事件。
我找不到这样的函数或任何可以用来构建它的东西。
我可以构建这种类型的东西,例如:
const (pure never)
Run Code Online (Sandbox Code Playgroud)
但这会忽略输入并且永远不会触发事件。
有没有办法做到这一点?还是我不应该做这种事情?
这个小程序的目的是显示三个按钮,第三个按钮的标签最初为"0",之后是最后点击按钮的索引.现在,按钮的数量和其他按钮的标签是不变的.
当我使用ghcjs编译这个自包含文件并在浏览器中加载Main.jsexe/index.html时,我可以看到两个traceDyns在循环中触发,两者总是具有值0.据我所知,什么都不应该发生直到单击一个按钮,因为_el_clicked为系统的其余部分提供信息.
另外,请注意我正在使用mapDyn (fst . head . Map.toList)以提取所选按钮的索引 - 我不确定这是否正确,但无论哪种方式我都不知道导致无限循环的原因.
{-# LANGUAGE RecursiveDo #-}
module Main where
import Reflex
import Reflex.Dom
import qualified Data.Map as Map
dynButton
:: MonadWidget t m
=> Dynamic t String
-> m (Event t ())
dynButton s = do
(e, _) <- el' "button" $ dynText s
return $ _el_clicked e
-- widget that takes dynamic list of strings
-- and displays a button for each, returning
-- an event of chosen button's …Run Code Online (Sandbox Code Playgroud) 我只是从reflex-dom库开始,我无法完全弄清楚使用对话框的正确和便捷的方法。
显示对话框通常意味着<body>在用户的末尾添加一些元素,并在用户单击某个按钮,背景或按下按钮(例如转义)时将其删除。但是,从某些嵌套的小部件执行此操作意味着将事件(“显示对话框”)冒泡到顶部,这可能很笨拙。还有其他方法可以很好地做到这一点吗?我只是看了markup.rocks,似乎使用了一些JS / jQuery hacks。
我可以决定不使用模式对话框(毕竟这可能不是一个坏选择),但是对于某些事情,我可能真的需要它。
这是Acess的一个跟进问题,一个带有reflex-dom客户端的servant服务器:
如果我在Web浏览器中运行客户端代码,一切正常.但是,如果我在gtk3(和Debian)下运行webkit中的客户端代码,我可以在服务器中看到请求,但客户端没有收到任何响应.
我想,这又是某种安全性或CORS问题.我发现这篇文章如何从2012年开始禁用webkit gtk中的web安全性(跨源reequest),因为这个bug 不可能https://bugs.webkit.org/show_bug.cgi?id=58378.如果我看看这个bug,它会说:状态:已解决固定.提到的SO帖子的第二个答案显示了未指定文件中的一些设置.
我的问题是:在哪里(目录和文件),我必须说明什么,从WebkitGtk客户端访问服务器.
我是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!" …Run Code Online (Sandbox Code Playgroud) 我在Haskell中使用Reflex,并试图创建一个事件,该事件会触发(出于问题目的)一段指定的时间,比如说2秒。但是,计数器应在原始事件触发时重置,以便如果原始事件相隔1秒触发两次,则第二个事件应仅触发一次:最后一个原始事件后2秒。
我设法实现了这种行为
delayedReset :: MonadWidget t m => Event t () -> m (Event t ())
delayedReset ev = fmap (switch . current) . widgetHold (return never) $ timer <$ ev
where
timer = delay 2 =<< getPostBuild
Run Code Online (Sandbox Code Playgroud)
但是使用widgetHold似乎有些矫kill过正。似乎我们只应该真正需要MonadHold约束。有没有更惯用的方式编写此函数?