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 モナドにあることです。したがって、それらを使用すると、動作は になりますが、動作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
コードはコンパイルされますが、機能しません。