Hi Adam, thanks for the responses!
Am Donnerstag, den 18.03.2021, 09:51 -0400 schrieb Adam Chlipala: > > Ur/Web doesn’t support canvas drawing out of the box, but I found > > https://github.com/fabriceleal/urweb-canvas/. Using a library like that > > was simple enough. Unfortunately, it didn’t cover the full Canvas API > > yet, and it seemed that adding the missing functions would require more > > boiler plate than I wanted to write right now. > > I can see how that makes sense for a quick pilot to evaluate the > language, though I expect it's pretty cost-effective to extend that > library with general Canvas features, for any kind of production app > (and then everyone else gets to benefit from the improvements!). Absolutely! And _after_ having refactored “my” JS code and learned about how to FFI-integrate it, I probably would have been more confident in just extending the library :-) > > Obviously, I need to connect the above function to a source/signal with > > the game state. I found that this works, although I wonder if this is > > an idiomatic way to do so: > > > > <canvas id={canvas_id} align="center" width=500 height=400/> > > <dyn signal={ > > ui <- signal ui_state; > > return <xml><active code={ > > drawDisplayState canvas_id (displayState ui); > > return <xml></xml> > > }/></xml> > The idiomatic way would be to use the features of the FFI for adding > change listeners on signals. You may have been thrown off by the > fact that the library you took as inspiration does no such thing! > You'll find JavaScript function "listen" documented briefly on page > 59 of the currently posted reference manual. Yes, I remembered that mention, but given that both the source and the code I want to invoke upon changes already lives in “Ur world” it felt wrong to reach for the FFI. And it was expressible with just non-FFI- features, as shown above… I guess either way is just a way to deal with the fact that I am doing something uncommon (running possibly effectful code upon changes to the signal). Given that it _is_ expressible with high-level abstractions (dyn+active) makes me wonder if there shouldn’t be a Basis.listen : signal a -> transaction a -> transaction unit or so, with sufficient documentation about when to use it and what to keep in mind. But maybe I shouldn’t ask for exposing underlying primitives before I really needed them a few times – it could be that I’d learn more idiomatic ways and notice that they are really rarely needed. > However, I also think of the type `source xbody` as a bad code > smell. It is usually better to put your fundamental data model in > sources and then derive HTML from them using <dyn> tags. That’s what I ended up doing in the end, and it’s probably cleaner. (Although a part of me, when it sees a data type T that is only deconstructed by a single function T -> A, wonders why not create values of type A directly. At least in a pure language.) > That would be great to see someone add! You can actually get pretty > good generic printing using conversion to JSON already, though. Ah, I didn’t look at the JSON stuff yet. Thanks for the hint! > > Irrefutable patterns in `p <- e; e` are useful, and I missed them also > > in `fn p => …`, especially when working with association lists. > Actually, irrefutable patterns do work with anonymous functions! > Something else must have gone wrong to throw you off. Maybe your > example was missing parentheses around the pattern. Indeed! I guess I didn’t try hard enough. That’s a relief :) > > The CSS parser didn’t like some property names I was using: > > “Invalid string -webkit-hyphens passed to 'property'” > Ah, sounds like I should just change the function that validates > property names. The implementations in SML and JavaScript both force > property names to start with letters or underscores. Is it clear > that hyphens should be allowed as well, with no further restrictions? I hope the diagram at https://www.w3.org/TR/css-syntax-3/#ident-token-diagram is the right one. Looks like it may start with a single hyphen, but that hyphen must be followed by letters or non-ASCII. > I would like to see algebraic datatypes and polymorphic variants > unified in a complete rewrite of Ur/Web some day. For now, variants > are really only worth using in connection with metaprogramming. I > have almost never written code with a variant of known type. I had code like this: datatype color = Black | White type gameState = { Goes_first : color, Phase : phase, Board : list (coord * option color), Chosen : { Black : option int, White : option int }, Placed : { Black : option int, White : option int }, } and more such “records that are total maps from the set of colors” I wonder if using a variant for color would have allowed me to avoid helpers like the following fun forColor r c = case c of | White => r.White | Black => r.Black fun setColor r c x = case c of | White => r -- #White ++ { White = x } | Black => r -- #Black ++ { Black = x } or at least write them more nicely. Cheers, Joachim -- Joachim Breitner m...@joachim-breitner.de http://www.joachim-breitner.de/ _______________________________________________ Ur mailing list Ur@impredicative.com http://www.impredicative.com/cgi-bin/mailman/listinfo/ur