我在threepenny-gui(TPG)中使用了IORef的一个小例子:
testIORef :: IORef String -> Window -> UI ()
testIORef ref window = void $ do
return window # set title "Test IORef"
inCell <- UI.input
outCell <- UI.input
-- When value changes write to IORef
on UI.valueChange inCell $ \_ -> do
inValue <- get value inCell
liftIO $ writeIORef ref inValue
-- function that reads the IORef and sets the value of an element with it
let setValue oc = do
newVal <- liftIO $ readIORef ref
element oc # set value newVal
-- When enter is pressed update the value of the output
on UI.keydown inCell $ \c -> if (c==13) then setValue outCell else return outCell
getBody window #+ [ column [ grid [[string "In cell :", element inCell]
,[string "Out cell:", element outCell]
]
, string "Cells should update while typing."
]
]
我正在尝试将其更改为使用TPG中的Reactive内容。我已经从事件valueChange和keyDown:
制作了行为inValue <- stepper "0" $ UI.valueChange inCell
inEnter <- stepper "0" $ fmap show $ filterE (\kc-> kc==13) $ UI.keydown inCell
但我仍然坚持如何使用这些行为来保存/获取IORef的值。问题是IORef调用将在UI monad中,所以如果我使用它们,行为将是Behavior (UI a)
,但是他们不会使用sink
。我知道在这种情况下我不需要使用IORef(例如货币转换示例) - 但在我的实际情况下我会这样做。
编辑: 我尝试编写自己的属性:
valueUI :: ReadWriteAttr Element (UI String) String
这样我就可以使用Behavior (UI String)
设置属性:
inEnter <- stepper "0" $ fmap show $ filterE (\kc-> kc==13) $ UI.keydown inCell
let getValue = fmap (const $ liftIO $ readIORef ref) inEnter
element outCell # sink valueUI getValue
代码编译但不起作用。