代码可以编译,但运行时会陷入无限递归循环。循环进入的位置并不明显,尤其是在使用递归 do 或 monadfix 时。尝试在浏览器中调试时,它在 rts.js 行 6086 处的 fixIO 中找到循环评估
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MonoLocalBinds #-}
import Reflex.Dom
import qualified Data.Text as T
main :: IO ()
main = mainWidget game
game :: MonadWidget t m => m ()
game = elClass "div" "game" $ do
elClass "div" "game-board" $ do
rec
stateEv <- board stateEv [["","",""],["","",""],["","",""]]
elClass "div" "game-info" $ do
elClass "div" "statu" $ blank
elClass "ol" "todo" $ blank
board :: MonadWidget t m
=> [[Event t T.Text]]
-> [[T.Text]]
-> m [[(Event t T.Text)]]
board s iss = elClass "div" "board" $ do
el "div" $ do
elClass "div" "status" $ text "Next player: X"
mapM (boardRow s) iss
boardRow :: MonadWidget t m
=> [[Event t T.Text]]
-> [T.Text]
-> m [(Event t T.Text)]
boardRow s is = elClass "div" "board-row" $ mapM (square s) is
square :: (
PostBuild t m
, DomBuilder t m
, MonadHold t m
)
=> [[Event t T.Text]]
-> T.Text
-> m (Event t T.Text)
square stateEv i = do
rec
let ev = domEvent Click e
ev' = updated dyn
ev'' = tagPromptlyDyn dyn ev
dyn = tooglePlayer <$> dynBool
dyns <- mapM (holdDyn i) (concat stateEv)
dynBool <- toggle True $ updated $ distributeListOverDyn dyns
(e, _) <- elAttr' "button" ("type" =: "button" <> "class" =: "square") $ dynText dyn
return ev''
tooglePlayer :: Bool -> T.Text
tooglePlayer True = "X"
tooglePlayer False = "O"