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

Popular posts from this blog

Django REST Framework perform_create: You cannot call `.save()` after accessing `serializer.data` -

Why does Go error when trying to marshal this JSON? -