stefan-hoeck / idris2-dom

Javascript DOM bindings for Idris2
BSD 2-Clause "Simplified" License
47 stars 7 forks source link

Missing Promise API #56

Open petithug opened 1 month ago

petithug commented 1 month ago

I extended idris2-dom with the Types/Prims API for WebRTC, but now I am stuck because many of the APIs are returning a Promise. Actually the first API where I encounter that issue is enumerateDevices in MediaStream, which returns a Promise (Array MediaDeviceInfo).

Now in JS (forgetting about the async/await stuff, which seems to be just syntactic sugar) there are 3 API for promises: then, catch, and finally. If the then API took a single callback, I could understand how to design an Idris monad for that. But it's the fact that there is two callbacks that makes it difficult for me to see what the Idris code would look like. For example we may want to chain more computations after a failure (maybe with an implementation of Alternative?)

But more concretely, here's a JavaScript snippet that uses the enumerateDevices API (from https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices):

if (!navigator.mediaDevices?.enumerateDevices) {
  console.log("enumerateDevices() not supported.");
} else {
  // List cameras and microphones.
  navigator.mediaDevices
    .enumerateDevices()
    .then((devices) => {
      devices.forEach((device) => {
        console.log(`${device.kind}: ${device.label} id = ${device.deviceId}`);
      });
    })
    .catch((err) => {
      console.error(`${err.name}: ${err.message}`);
    });
}

I suppose the equivalent Idris code would start as something like this:

test : JSIO ()
test = do
  w <- window
  n <- navigator w
  md <- mediaDevices n
  devs <- enumerateDevices md

What would the remaining of the JS code look like in Idris2?

ysangkok commented 1 month ago

Since PureScript and Idris2 are both strict, it seems to me that it should be possible to port the PureScript libraries for this. Or am I somehow wrong about this?

PureScript has the Aff monad and a separate thin Promise API, and a library to connect them, Promise.Aff. A minimal usage example would be something like Web.Clipboard.

I suppose the biggest issue with this is that the Aff implementation is admittedly complicated, so maybe it won't be easy to port. But we use it at work and it's been comfortable, so I'd be happy to see something like it in Idris.