Javascript function wants Effect callback, but I'm in my own monad

My situation is as follows:

  • I have a halogen application where all the components live inside my own AppMonad (which is just derived from ReaderT and has, for example, the baseUrl for external requests stored).
  • I’m wrapping a Javascript library that wants a function String -> Effect (Array a) (for some a, not important).
  • I have a function fetchStuff :: String -> AppMonad (Array a) and I’d like to pass that to the JS function.

How do I do that elegantly? I mean, I can just run the app monad, again passing the proper parameters. But that seems a bit clumsy.

1 Like

In the general case this is a complex problem. Various solutions like monad-control (in haskell) and Concur’s shiftMap were invented for this but none of them seem completely satisfactory (and might actually conceal bugs), so I would recommend just writing your own simple helper functions that work for your use case until you need a more general thing.

In your simple reader case you can hide the clumsiness behind a function that reads the value, extracts the effect value and calls the js function.

runIO :: ReaderT Effect a -> (Effect a -> Effect r) -> ReaderT Effect r
runIO m f = do
  r <- ask
  liftEffect (f $ runReaderT m r)
2 Likes