ajnsit / concur

An unusual Web UI Framework for Haskell
https://ajnsit.github.io/concur/
BSD 3-Clause "New" or "Revised" License
305 stars 21 forks source link

liftIO in Widget causes strange behavior #8

Open mpdairy opened 6 years ago

mpdairy commented 6 years ago

I'm working on a nifty way to do forms, which will also hopefully be able to handle text inputs that update every key press. However, I ran into my form elements returning some really weird results, and I narrowed it down to it being caused by widgets that have liftIO in them. For example, here's a Widget I made as I was trying to figure out the problem:

testNonStateT :: Widget HTML b
testNonStateT = forever $ do
  _ <- simStateT ("one", "two", "three")
  return ()
  where
    simStateT s = do
      r <- (do
               r <- inputEnter' $ s ^. _1
               liftIO $ print "hey there!"
               return $ s & _1 .~ r)
           <|>
           (do
               r <- inputEnter' $ s ^. _2
               liftIO $ print "hey there!"
               return $ s & _2 .~ r)
           <|>
           (do
               r <- inputEnter' $ s ^. _3
               liftIO $ print "hey there!"
               return $ s & _3 .~ r )
      liftIO $ print r
      simStateT r

inputEnter' :: String -> Widget HTML String
inputEnter' t = inputEnter [ A.value . JS.pack $ t ]

When I try this, the third one will work fine, but the second one gets the third input box's return value, and the first gets the second's. However, if I uncomment the liftIO $ print "hey there!" lines, it works fine.

I'm using Concur.VDOM.

ajnsit commented 6 years ago

That's really weird. I'll take a look.

ajnsit commented 6 years ago

From initial investigation it seems to be a bug in ghcjs-vdom. I'll look at it more later today.

mpdairy commented 6 years ago

Did you ever find out anything more about this? If it's just a vdom bug, would you recommend that I just use a different concur backend for now?

ajnsit commented 6 years ago

I looked at it a little bit and then got busy with other things. Thanks for reminding me!

I'm still not sure if this is a GHCJS bug or a ghcjs-vdom bug. But I found a quick way to solve this - add some strictness. So for example you can use {-# LANGUAGE BangPatterns #-} and then do - !r <- inputEnter' $ s ^. _1 .

Of course if you wish, you can always use Concur-React instead of Concur-VDOM. The React backend doesn't seem to suffer from the same issue, and it's also relatively better maintained (Since ghcjs-vdom is bitrotten at this point).

mpdairy commented 6 years ago

Ok thanks! I'll try concur-react or fall back to using strictness.