<div dir="ltr"><div><font face="monospace, monospace">My previous messages in this mailing list for July 2015 are mostly obsolete, because I have revised my code. </font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">I'm still having trouble correctly using monadic IO to:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">- run an SQL SELECT transaction; and then </font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">- use the results to build XML </font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">- within the context of the Crud demo (which imposes certain type requirements of its own).</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Problem:</font></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">An excerpt from my code is shown below. In this scenario, the user is editing a "child" record, using a data-bound <select> widget to select a primary key in the "parent" table, called `status`:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  Widget = (fn [nm :: Name] => </font></div><div><font face="monospace, monospace">    let</font></div><div><font face="monospace, monospace">      val statusOptionsList = </font></div><div><font face="monospace, monospace">        queryL1 (SELECT Id, Nam FROM status ORDER BY Nam) </font></div><div><font face="monospace, monospace">      val statusOptions = </font></div><div><font face="monospace, monospace">        List.mapX </font></div><div><font face="monospace, monospace">          (fn r => <xml><option>{r.Nam}</option></xml>)</font></div><div><font face="monospace, monospace">          statusOptionsList  (* <<== LINE 44 IN ERR MSG BELOW! *)</font></div><div><font face="monospace, monospace">    in</font></div><div><font face="monospace, monospace">      <xml></font></div><div><font face="monospace, monospace">        <select{nm}></font></div><div><font face="monospace, monospace">          {statusOptions} </font></div><div><font face="monospace, monospace">        </select></font></div><div><font face="monospace, monospace">      </xml></font></div><div><font face="monospace, monospace">    end)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">I keep getting errors "unification failure" and "incompatible constructors", eg:</font></div><div><font face="monospace, monospace"><br></font></div><div><span style="font-family:monospace,monospace">/home/scott/wrk/urweb/crud2foreign_queryL1/crud2foreign.ur:44:14: (to 44:31) Unification failure</span><br></div><div><font face="monospace, monospace">Expression:  statusOptionsList</font></div><div><font face="monospace, monospace">  Have con:  transaction (list $<UNIF:U128::{Type}>)</font></div><div><font face="monospace, monospace">  Need con: list $(([Nam = xml ([]) ([]) ([])]) ++ <UNIF:U238::{Type}>)</font></div><div><font face="monospace, monospace">Incompatible constructors</font></div><div><font face="monospace, monospace">Have:  transaction</font></div><div><font face="monospace, monospace">Need:  list</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Can anyone see the error in my 'Widget' code further above?</font></div></div><div><br></div><div><font face="monospace, monospace">----</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Important: My code does not occur in isolation. The result of my code building the Widget will later be passed on to module Crud from the existing Ur/Web demo, which has the following signature:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><a href="http://www.impredicative.com/ur/demo/crud2.html">http://www.impredicative.com/ur/demo/crud2.html</a></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><a href="https://github.com/StefanScott/urweb-crud2foreign-queryL1/blob/master/crud.urs">https://github.com/StefanScott/urweb-crud2foreign-queryL1/blob/master/crud.urs</a></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">(* crud.urs *)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">con colMeta = fn (db :: Type, widget :: Type) =></font></div><div><font face="monospace, monospace">                 {Nam : string,</font></div><div><font face="monospace, monospace">                  Show : db -> xbody,</font></div><div><font face="monospace, monospace">                  Widget : nm :: Name -> xml form [] [nm = widget],</font></div><div><font face="monospace, monospace">                  WidgetPopulated : nm :: Name -> db -> xml form [] [nm = widget],</font></div><div><font face="monospace, monospace">                  Parse : widget -> db,</font></div><div><font face="monospace, monospace">                  Inject : sql_injectable db}</font></div><div><font face="monospace, monospace">con colsMeta = fn cols :: {(Type * Type)} => $(map colMeta cols)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">val int : string -> colMeta (int, string)</font></div><div><font face="monospace, monospace">val float : string -> colMeta (float, string)</font></div><div><font face="monospace, monospace">val string : string -> colMeta (string, string)</font></div><div><font face="monospace, monospace">val bool : string -> colMeta (bool, bool)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">functor Make(M : sig</font></div><div><font face="monospace, monospace">                 con cols :: {(Type * Type)}</font></div><div><font face="monospace, monospace">                 constraint [Id] ~ cols</font></div><div><font face="monospace, monospace">                 val fl : folder cols</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">                 table tab : ([Id = int] ++ map fst cols)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">                 val title : string</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">                 val cols : colsMeta cols</font></div><div><font face="monospace, monospace">             end) : sig</font></div><div><font face="monospace, monospace">    val main : unit -> transaction page</font></div><div><font face="monospace, monospace">end</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">So module Crud will impose some requirements on the signature of Widget.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">But so far, I appear to be getting these "unification failure" and "incompatible constructors" errors *before* passing the result on to the Crud module.</font></div><div><font face="monospace, monospace"><br></font></div><div><br></div><div><font face="monospace, monospace">Discussion:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">My code is based on a somewhat similar example in the chat room PDF, which runs a SQL SELECT transaction on a table (of chat rooms) to build an XML fragment.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  <a href="http://adam.chlipala.net/papers/UrWebPOPL15/UrWebPOPL15.pdf">http://adam.chlipala.net/papers/UrWebPOPL15/UrWebPOPL15.pdf</a></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">The chat room PDF provides an example usage of queryL1 and List.mapX (in figure 2, at the top of page 4):</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Also on page 4, the chat room PDF provides the following descriptions of functions queryL1 and List.mapX:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  queryL1 - Return as a list (justifying the L) the results of a query that only returns columns of one table (justifying the 1).</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  List.mapX - Apply an XML-producing function to each element of a list, then concatenate together the resulting XML fragments to compute the result of mapX.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Note (1): The above description of queryL1 says that it returns a "list". It does not say that it returns a "transaction" or a "transaction list" - but this may of course be due to an informal use of language here.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Note (2): The invocation of </font><span style="font-family:monospace,monospace">queryL1 and </span><span style="font-family:monospace,monospace">List.mapX, and the way the result produced by queryL1 is "consumed" by List.mapX, are different in the chat room PDF versus in my program, eg:</span></div><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">(a) The chat room PDF uses `<-` notation (see the first line of function main);</span></div><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">(b) The result of calling List.mapX in the chat room PDF is consumed by `main() : unit -> transaction page`;</span></div><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">(c) In my code, the result must be appropriate for signature of Widget declared in the Crud module.</span></div><div><font face="monospace, monospace"><br></font></div><div><br></div><div><font face="monospace, monospace">Conjectures:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">There must be something wrong with my syntax attempting to use monadic IO to get the result of the SQL transaction and use it to build the XML fragment, and/or with the overall "flow" of function calls I'm using to run the SQL and build the XML expression.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Furthermore, I'm not even sure if it's possible to put the result of a *transaction* into the place where I want to put it: in the definition of function Widget, whose signature is already declared in crud.urs as:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Widget : nm :: Name -> xml form [] [nm = widget]</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Maybe I could phrase my question some other way: Can I even *use* functions such as queryL1 or queryX1 to define a function satisfying the signature of Widget above? </font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Those functions return type `transaction` but Widget expects something of type `xml` so maybe I'm going about this all wrong??</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">But then again, I do expect that I should be able to somehow "unbox" the result of a transaction, like any other monad. I don't know if there is a trivial pattern-matching syntax commonly used for this (as with using a case statement on Some or None in the Option monad) - or perhaps its part of the notation involving `;` and `<-` and `return`.</font></div><div><br></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Motivation:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">I'm attempting to construct a data-bound <select> widget to let the user easily edit a foreign-key field in a "child" record (where the options in the <select> element would display a list of <option> elements, each containing a value of the "parent" table's primary key).</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">This kind of data-bound foreign-key <select> widget is essential for writing practical web applications using Ur/Web.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Remark:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">I apologize for using Ur/Web as my language for starting to try to use monads, rather than Haskell or ML (although I have tried to read as much as possible on monads in Haskell and ML for the past year, as a way to prepare to use Ur/Web). </font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">I think seeing an example of how to run SQL to generate XML to build this sort of data-bound <select> widget in Ur/Web (in the context of the existing Crud demo) would be the most motivational example to really clarify the Transaction monad to me.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">As Adam has remarked, I am a monadic newbie - in the sense that I still don't grasp the syntax to pass around and access values in a monad. </font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">On the other hand, I have been trying to learn this stuff - studying Haskell and ML and Ur/Web. </font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">The fact that I can formulate the question as follows...</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  Function `queryL1` returns type `transaction (list $fs)` - How can I get the `list $fs` part and pass it to `List.mapX` - which expects type `list`?<br></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">...Is that good or bad? Does it mean I'm starting to grasp it - or am I still totally lost?</font></div><div><br></div><div><br></div><div><font face="monospace, monospace">Complete source:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">The complete example is on github, here:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><a href="https://github.com/StefanScott/urweb-crud2foreign-queryL1">https://github.com/StefanScott/urweb-crud2foreign-queryL1</a></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Complete error message:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">The complete compiler error message is Issue 1 on the same github repo:</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><a href="https://github.com/StefanScott/urweb-crud2foreign-queryL1/issues/1">https://github.com/StefanScott/urweb-crud2foreign-queryL1/issues/1</a></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Thanks!</font></div><div><br></div></div>