在threepenny gui中使用IORef

时间:2015-05-01 11:39:01

标签: haskell threepenny-gui ioref

我试图在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不是最新的。

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

感谢。

2 个答案:

答案 0 :(得分:2)

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

let outValue = (const refVal) <$> inValue

指定outValueBehavior,其值恒定且等于refValue。反过来,后一个值来自

refVal <- liftIO $ readIORef ref

表示IORef monad中UI此时存储的值。

使用IORef时,您希望在更改内容时读取引用的值,并使用此值修改UI内容,例如:

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

出于一致性(操作顺序)的原因,不建议使用IORef作为Behavior的来源 - 它是后者还是前者。

答案 1 :(得分:0)

我不是三便秘的专家,但这是我的猜测。

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

-- 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