[Ur] Given a value of a "transactional" type, how can it be used in an expression expecting a different, "non-transactional" type?

Stefan Scott Alexander stefanscottalexx at gmail.com
Sun Jul 19 00:03:13 EDT 2015


Summary:

Adam's initial guess is totally correct: this is indeed "one of the
standard 'newbie' problems with monadic IO, in common with Haskell."

Specifically, given a "parent" table which contains the following records...

     Id  |  Nam
  -----------------
     1   |  One!
     2   |  Two!
     3   |  Three!

...I want to use monadic IO to run an SQL SELECT transaction to get the
above "parent" records, and then use the result to generate the <xml> for a
<select> widget (on the "child" record form) that would look like this:

  Widget = (fn [nm :: Name] =>
    <xml>
      <select{nm}>
         <option>One!</option>
         <option>Two!</option>
         <option>Three!</option>
      </select>
   </xml>)

My incorrect code looks like this:

  Widget = (fn [nm :: Name] =>

  statusOptions <-
    queryX1 (SELECT Id, Nam FROM status ORDER BY Nam)
    (fn r => <xml><coption value={r.Id}>{r.Nam}</coption></xml>);

    return;

  (* Another incorrect alternative which I attempted for the above line:

     return statusOptions;

     I also tried simply OMITTING the above line involving 'return' *)

    <xml>
      <select{nm}>
        {statusOptions}
      </select>
    </xml>)

I understand that the above code needs to be corrected to somehow
"separate":

- the chunk of monadic IO SQL SELECT transactional code

from

- the chunk of code used to build the <xml>

However, I can't figure out where to situate the first, transactional chunk
in the context of the above function definition.


Relevance:

The task at hand (building a data-bound <select> widget to enable users to
easily edit a foreign-key field) is:

(a) extremely urgent (because without such a widget, Ur/Web cannot be used
to create practical web database applications); and

(b) probably relatively straightforward (all that is needed is to get the
monadic syntax right, in order to grab a value from the SQL SELECT
transaction and then use it to build the <xml>).

Given (a) and (b), I trust that such a question is appropriate to this
list, and I hope that someone will eventually be able to provide the
correct syntax needed in this case.

This will not only help a monadic newbie like me learn the correct syntax -
it will also allow me to contribute this urgently needed data-bound
<select> widget.

Without a data-bound <select> (or auto-complete / type-ahead widget, which
I would also like to work on later), Ur/Web will continue to be unusable
for practical web database application development.


Details:

My attempts to produce the above <xml> from the above SQL include the 3
incorrect examples below:

Widget = (fn [nm :: Name] =>
statusOptions <-
  queryX1 (SELECT Id, Nam FROM status ORDER BY Nam)
  (fn r => <xml><coption value={r.Id}>{r.Nam}</coption></xml>);
  return;
  <xml>
    <select{nm}>
      {statusOptions}
    </select>
  </xml>)

Widget = (fn [nm :: Name] =>
statusOptions <-
  queryX1 (SELECT Id, Nam FROM status ORDER BY Nam)
  (fn r => <xml><coption value={r.Id}>{r.Nam}</coption></xml>);
  return statusOptions;
  <xml>
    <select{nm}>
      {statusOptions}
    </select>
  </xml>)

Widget = (fn [nm :: Name] =>
statusOptions <-
  queryX1 (SELECT Id, Nam FROM status ORDER BY Nam)
  (fn r => <xml><coption value={r.Id}>{r.Nam}</coption></xml>);
  <xml>
    <select{nm}>
      {statusOptions}
    </select>
  </xml>)

(See also Note [1] at the end of this post.)

The type error from the compiler produced by the first fragment above can
be seen here:

https://github.com/StefanScott/urweb-crud2foreign/issues/1


Survey of the Ur/Web literature, searching for relevant similar examples:

For the current use case (extracting a value from an SQL SELECT transaction
in order to build an <xml> fragment compatible with the Crud2 demo), I
searched for any Ur/Web examples which might provide something close to the
syntax I needed.

The closest examples I could find in Ur/Web are the Crud2 demo, and the
chat room PDF (as mentioned in my original post here:

http://www.impredicative.com/pipermail/ur/2015-July/002064.html

Also, the UPO jfac example (excerpted below) seems highly relevant.


A more complete list of relevant (and possibly relevant) examples is shown
below:

Relevant - the "Crud2 demo":

(1) http://www.impredicative.com/ur/demo/crud2.html

(2) https://github.com/urweb/urweb/blob/master/demo/crud.urs

(3) https://github.com/urweb/urweb/blob/master/demo/crud.ur

(4) https://github.com/urweb/urweb/blob/master/demo/crud2.ur

Relevant - the "chat room PDF":

(5) http://adam.chlipala.net/papers/UrWebPOPL15/UrWebPOPL15.pdf - the "chat
room PDF"

Relevant - the "jfac" example from UPO:

(6) https://github.com/achlipala/upo/blob/master/examples/jfac.ur

Possibly relevant:

(7) https://github.com/urweb/urweb/blob/master/demo/form.ur

(8) https://github.com/urweb/gui/blob/master/select.ur

(9) https://github.com/urweb/urweb/blob/master/tests/cselect.ur

(10) https://github.com/achlipala/upo/blob/master/chooseForeign.urs

(11) https://github.com/achlipala/upo/blob/master/chooseForeign.ur

Note: I expect (8) and (9) to be relevant only *later*: when I attempt
build on the results of the <select> widget, in order to create an
auto-complete or type-ahead widget. This is also highly relevant for using
Ur/Web to create practical web database applications, as it a type-ahead /
auto-complete widget would support vastly more items in the drop-down.
However, it will be more complicated to create, because (a) instead of
relying on the HTML5 <select> element, it will instead need to use
something like two separate elements: one where the user can enter some
characters, and another to display the results, and (b) it will involve
using Ur/Web's FRP facilities, including syntax such as source, signal,
set, and get.


Difficulties:

(1) The types involved in the three most relevant examples (the Crud2 demo,
the chat room PDF and the UPO jfac example) are not compatible, so the
output from the SQL SELECT transaction needs to be modified somehow in
order to be able to use it to build the <xml> fragment.

(2) The UPO jfac example (shown below) effectively separates the monadic
SQL SELECT transaction from the <xml> fragment - with lots of
further-indented intervening code in between. I have been able to figure
out how to do a similar kind of "separation" in my code.


Possibly very relevant code from the UPO jfac example, here:

https://github.com/achlipala/upo/blob/master/examples/jfac.ur

  restaurants <- queryX1 (
    SELECT restaurant.RestaurantName, restaurant.Neighborhood
    FROM restaurant
    ORDER BY restaurant.RestaurantName, restaurant.Neighborhood)
    (fn r => <xml>
               <coption value={r.RestaurantName ^ "^" ^
r.Neighborhood}>{[r.RestaurantName]}
                 {case r.Neighborhood of
                      "" => <xml/>
                    | s => <xml>({[s]})</xml>}</coption></xml>);

[ ... many more lines of further-indented code ... ]

  <div class="form-group">
  <label>Where?</label>
  <cselect source={whichR} class="form-control">
  {restaurants}
  </cselect>
  </div>

I naively tried to model my code on the above UPO jfac example, while also
taking into account the code from the Crud2 demo and the chat room PDF.

I now see that the "many more lines of further-indented code" in the middle
of the UPO jfac example are somehow essential, in that they perform the
necessary "separation" of the transactional SQL code from the <xml>
fragment being built.

My code is incorrectly lumping everything together into one sequence, doing
the following:

- running the SQL transaction and assigns the resulting value to identifier
'statusOptions'

- using (a 'return' and) a semi-colon

- immediately attempting to return the <xml>

So I need to somehow completely separate the transactional code which
assigns a value to 'statusOptions' from the code which generates the <xml>.

I just can't figure out how to do this.


Further information:

In my original post, I did the following:

(a) created a github repo containing an initial, oversimplified (and
working!) test case, just to make sure I wrote the non-monadic part of the
code correctly:

https://github.com/StefanScott/urweb-crud2local

(b) created a separate (non-working!) github repo adding the monadic code:

https://github.com/StefanScott/urweb-crud2foreign

(c) copied the compiler error message from (b) into an Issue in the same
github repo, to help with diagnosis (while also trying to avoid cluttering
this list with lengthy compiler output):

https://github.com/StefanScott/urweb-crud2foreign/issues/1

I understand that people are busy, so my goal has been to present the
question as clearly and conveniently as possible, in order to make it as
painless as possible for someone in the Ur/Web community to provide an
answer, so that I can create a data-bound <select> to allow users to easily
edit foreign-key fields, which is essential in order for programmers to be
able to use Ur/Web to be used to develop practical web database
applications.


Note [1]:

More generally, we would want the following <xml> fragment which includes
the 'value' attribute.

  Widget = (fn [nm :: Name] =>
    <xml>
      <select{nm}>
         <option value="1">Local One!</option>
         <option value="2">Local Two!</option>
         <option value="3">Local Three!</option>
      </select>
   </xml>)

But in this case we actually don't need the 'value' attribute shown above,
because...

- the uniqueness of the 'Nam' column in "parent" table; and

- the way the Parse function happens to work in this case of Crud2
(obtaining Nam from Id)

... avoids the need for this.

###
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.impredicative.com/pipermail/ur/attachments/20150719/43bcda08/attachment-0001.html>


More information about the Ur mailing list