What do you think of this approach to wrapping the web APIs?

Personally, I’m not very satisfied with the UX of the purescript-web libraries, so I sought out to make my own. I’m using a type class approach to trim down on all the conversions, very similar to the long abandoned dom-classy.

I’m also trying to follow the WHATWG spec very closely. I’m looking to have a module for each interface (at least the ones that add any sort of extra functionality), and use type classes to combine their functionalities. That being said, I’ll also be including relevant W3C interfaces as well.

It’s a huge API to wrap and still very incomplete (I’ve just been adding functionality as I need it), but I think there’s enough there to make the approach clear.

check out the code

So yeah, just looking to get some feedback before pushing forward.

  • Does it look like something you’d want to use?
  • Do you see a fatal design flaw? (I’ve already fixed a few of those myself along the way)
1 Like

Did you first clarify why dom-classy, which uses a similar approach to your idea, was abandoned?

Hi @ursi,

I ran spago docs to your repository and checked it out that way. I think you’ve got enough that this library can be studied. Thank you.

You had those neat Web IDL headers extracted from the WatWg specs. I wonder how close you got? Do you think we could just generate this kind of headers from the IDL definitions?

I did look at the function signatures a bit.
One thing particularly striking my eye there is that you correctly identified different events in WHATWG.HTML.Mixin, but there is no single event type noted there, everything’s just same event. Also the type forall b. (Event -> Effect b) without ‘b’ taking part in any typeclass means that the result can only be discarded.

Please, I beg you, use the types from purescript-web and build on top of them. That’s the whole point of those libraries! To provide a complete API based on the specs, and then people have a common base with which to use so that other things can be opinionated but at least still be interoperable.

10 Likes

I did not, I guess I will.

One thing particularly striking my eye there is that you correctly identified different events in WHATWG.HTML.Mixin, but there is no single event type noted there, everything’s just same event

Interesting, I was just copying the GlobalEventHandlers interface which defines everything as just an EventHandler (although not quite everything now that I look at it). But you’re right, it looks like in other parts of the document it specifies more specific interfaces for each event, and I definitely should use those instead.

Also the type forall b. (Event -> Effect b) without ‘b’ taking part in any typeclass means that the result can only be discarded.

I was recently questioning this myself as well. I could see myself changing b to Unit, however I want to say there is some functionality where if you return false in an event handler it does something (I think it cancels it), so that would be an argument to leave it polymorphic.

1 Like

If this is what people want I can do that. Since I put all the types in one file it would be a very easy change. I only made different types because I figured usage of the two libraries would be mutually exclusive.

Also, regarding what @JordanMartinez said, since I can’t put in an issue on dom-classy due to it being archived, what was your reason for abandoning the project?

I abandoned dom-classy after introducing a lot more casts and conversions in the -web projects. Originally you’d have to do a chain of coercions if you wanted to go from HTMLElement to Node, for example.

After doing that, I found that using the classes became more annoying (to me personally) than using the explicit casts and coercions.

The downside of the class approach is it breaks hole-directed programming quite often, since when inserting holes you get missing instance errors and such rather than a suggestions for the hole. Also sometimes you have to provide explicit type signatures, as situations similar to fromFoldable <<< toUnfoldable arose fairly often, where things are polymorphic “in the middle” and you need to force a type for an instance to be chosen for it to work out.

I’m not saying it’s a hopeless cause, I just never really looked at fixing these problems too much, as really the library was just replicating the API but adding constraints rather than concrete types for the arguments rather than trying anything more imaginative. I live in hope that there is a better API, I just don’t have the willpower to work on it or maintain it given that I have my fingers in too many projects to be a good maintainer as it is. :wink:

2 Likes

You can potentially encode hierarchies with row-types in some way. This might give you better hole suggestions with a similar level of polymorphism.

1 Like