What can I do to eliminate the unsafePerformIO in this Reflex.Dom code?

181 Views Asked by At
main = mainWidget $
  el "div" $ do
    let fileInputConfig = FileInputConfig (constDyn Map.empty)
    fi <- fileInput fileInputConfig

    let uploads   :: Dynamic t [File]            = value fi
    upload        :: Dynamic t (Maybe File)      <- (return . fmap headMay) uploads
    getNameAction :: Dynamic t (Maybe (IO Text)) <- (return . fmap (getNameText <$>)) upload
    filename      :: Dynamic t (Maybe Text)      <- (return . fmap (unsafePerformIO <$>)) getNameAction

    el "div" $ dynText (show <$> filename)
  return ()
  where getNameText :: MonadIO m => File -> m Text
        getNameText = getName

I did my best to play connect-the-dots with the types but I couldn't find a path out without using unsafePerformIO. I think it's safe in this case, but obviously there are other similar things you might want to do that would not be safe.

1

There are 1 best solutions below

1
On BEST ANSWER

For things like this, you usually need performEvent. I don't have compiler/REPL at hand to provide more detail, and the function is sort-of hidden behind some typeclass hackery (https://github.com/reflex-frp/reflex/blob/9575a5660334fb8a617da1cd9aa1b522e8e4ddb7/src/Reflex/PerformEvent/Class.hs), but the gist of it is that if you have an event carrying IO, then you can run it wherever this event occurs.

Now, you've got the Dynamic, but you can

  • extract the event from it
  • maybe it doesn't need to be Dynamic (it doesn't make sense, as you don't want to peek at the IO value)