haskell - Monad: [UI Element] vs [Element] -
in following code sample tried create box number of select elements , combine selection list of values using behaviors. (code compiles/runs in ghci threepenny-gui)
{-# language recursivedo #-} module threepenny.gui import prelude hiding (lookup) import control.monad import data.list import data.traversable import data.maybe import data.monoid import qualified data.map map import qualified data.set set import qualified graphics.ui.threepenny ui import graphics.ui.threepenny.core hiding (delete) {----------------------------------------------------------------------------- (#) reverse function application: flip $ (#+) append dom elements children given element: parent #+ children (#.) returns ui element css class changed second parameter ------------------------------------------------------------------------------} gui :: io () gui = startgui defaultconfig setup fixedtextarea = ui.textarea # set style [("resize", "none"), ("height", "14px"), ("width", "500px")] combinedbeh :: monadio m => [element] -> m (behavior ([maybe int])) combinedbeh sl = sequencea <$> sequence blist blist = fmap (stepper nothing . ui.selectionchange ) sl selectdivwrong :: ui (element, behavior [maybe int]) selectdivwrong = let select options = ui.select # set style [("display","inline-block"), ("width", "150px"), ("margin", "0px 0px 4px 0px")] #+ fmap (\x -> ui.option # set ui.text (show x)) options selectionlist :: [ui element] selectionlist = replicate 6 $ select [0, 1, 2, 3, 4, 5] selectionlist' <- (sequence selectionlist :: ui [element]) bselectionlist <- combinedbeh selectionlist' mainbox <- ui.mkelement "selectdiv" # set style [("display","inline-block"), ("background-color", "#333344"), ("height", "200px"), ("width", "150px"), ("padding", "1px")] -- #+ (selectionlist) -- unsequenced list of ui elements. behavior (bselectionlist) should have info needs though(?). -- why (#+) not have same ui info bselectionlist ? return (mainbox, bselectionlist) selectdivcorrect :: ui (element, behavior [maybe int]) selectdivcorrect = let select options = ui.select # set style [("display","inline-block"), ("width", "150px"), ("margin", "0px 0px 4px 0px")] #+ fmap (\x -> ui.option # set ui.text (show x)) options selectionlist :: [ui element] selectionlist = replicate 6 $ select [0, 1, 2, 3, 4, 5] selectionlist' <- (sequence selectionlist :: ui [element]) bselectionlist <- combinedbeh selectionlist' mainbox <- ui.mkelement "selectdiv" # set style [("display","inline-block"), ("background-color", "#333344"), ("height", "200px"), ("width", "150px"), ("padding", "1px")] -- #+ (fmap pure selectionlist') return (mainbox, bselectionlist) setup :: window -> ui () setup window = void $ mdo (sdiv1, bsdiv) <- selectdivwrong text1 <- fixedtextarea # sink ui.text (show <$> bsdiv) (sdiv2, bsdiv2) <- selectdivcorrect text2 <- fixedtextarea # sink ui.text (show <$> bsdiv2) getbody window #+ [grid [ [element sdiv1] , [element text1] , [element sdiv2] , [element text2] ]] # set style [("background-color", "#eeeeee")]
initially wanted use selectdivwrong
figured out need modify selectdivcorrect
. problem don't understand why there functional difference. in both cases selectionlist
contains elements need added , bselectionlist
combines behaviors. i'm not sure how ui
handles state , events (and haven't used monads/applicatives whole lot yet), suspect in correct version combined ui
context added 'top level' , passed (#+)
(or ui.mkelement
?), remains unused in list of ui element
s in wrong version.
i'm still not sure if i'm missing anything, though. i'd sure , find explanation helps identify sort of issue in future, since found solution via trial , error. (also feel free rename question...)
they key point type ui element
denotes (monadic) action creates/manipulates/returns thing, whereas type element
denotes thing itself. sometimes, former creates new thing, returns old thing.
in case, selectionlist :: [ui element]
list of actions create thing (each).
in wrong version, first use sequence
execute actions in sequence, pass list #+
combinator, internally executes actions in sequence well. hence, actions executed twice, each element created twice.
in correct version, use sequence
execute actions in sequence , retain corresponding new things (element
) in list selectionlist'
. elements have been created once, , pass them whatever comes next. combinator pure
builds action returns existing thing, that's works.
in end, type of #+
may bit confusing, more transparent if accepted list [element]
instead of list [ui element]
. latter reduces syntactic noise, though, reduces need name individual elements.
Comments
Post a Comment