1

我正在尝试在threepenny-gui 中设置一个IORef,但我无法让它工作。在我的应用程序中, IORef 本身会更复杂,并且不会显示 - 但这个例子展示了我认为的问题。

这是我的尝试:

testIORef2 :: IORef String -> Window -> UI ()
testIORef2 ref window = void $ do
    return window # set title "Test IORef"

    inCell <- UI.input
    outCell   <- UI.input

    getBody window #+ [
            column [
                grid [[string " In cell::", element inCell]
                     ,[string "Out cell::"  , element outCell  ]]
            , string "Cells should update while typing."
            ]]

    -- When value changes write to IORef
    on  UI.valueChange inCell $ \_ -> do
        inValue <- get value inCell
        liftIO $ writeIORef ref inValue    

    -- Read the IORef
    refVal <- liftIO $ readIORef ref

    -- Behaviour which holds the string value in the input cell
    inValue <- stepper "0" $ UI.valueChange inCell
    -- Behaviour which holds the value in the ref
    let outValue = (const refVal) <$> inValue

    -- Set the value of the output cell to the outValue
    element outCell # sink value outValue

代码有点工作,但 outValue 不是最新的。

如何修复它以便按时更新。此外,欢迎对代码进行任何改进。

谢谢。

4

2 回答 2

2

您编写的代码可能不是您打算做的。线

let outValue = (const refVal) <$> inValue

指定outValue是 a Behavior,其值为常数且等于refValue。反过来,后一个值是从

refVal <- liftIO $ readIORef ref

这意味着它是此时存储IORefUImonad 中的值。


使用 时IORef,您希望在发生变化时读取引用的值,并使用该值来修改 UI 内容,例如:

on  UI.valueChange inCell $ \_ -> do
    inValue  <- get value inCell
    liftIO $ writeIORef ref inValue
    outValue <- liftIO $ readIORef ref    
    element outCell # set value outValue

出于一致性(操作顺序)的原因,不建议使用 aIORef作为 a 的来源Behavior——要么是后者,要么是前者。

于 2015-05-02T08:37:38.260 回答
0

我不是threepenny-gui的专家,但这是我的猜测。

您在事件处理程序之外编写的代码on只执行一次。因此,您希望outValue所述处理程序中包含更新,例如

-- When value changes write to IORef
on  UI.valueChange inCell $ \_ -> do
    inValue <- get value inCell
    liftIO $ writeIORef ref inValue    
    ... -- compute outValue
    element outCell # sink value outValue
于 2015-05-01T12:07:01.317 回答