<div dir="ltr"><div>Consider the (only) two occurrences of the identifier `Tab` in file crud.ur in the Crud demos, in the function `upd (r : int)`, on lines 126 and 138, underscored using the coomment `(*   ^^^  *)` in the excerpt quoted here below:<br></div><div><br></div><div><a href="http://hg.impredicative.com/urweb/file/010ce27228f1/demo/crud.ur#l126">http://hg.impredicative.com/urweb/file/010ce27228f1/demo/crud.ur#l126</a></div><div><br></div><div><a href="http://www.impredicative.com/ur/demo/crud.ur.html">http://www.impredicative.com/ur/demo/crud.ur.html</a><br></div><div><br></div><div> fso <- oneOrNoRows (SELECT tab.{{map fst M.cols}} FROM tab WHERE tab.Id = {[id]});</div><div>        case fso : (Basis.option {Tab : $(map fst M.cols)}) of</div><div>                             (*   ^^^  *)</div><div>            None => return <xml><body>Not found!</body></xml></div><div>          | Some fs => return <xml><body><form></div><div>            {@foldR2 [fst] [colMeta] [fn cols => xml form [] (map snd cols)]</div><div>              (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] v (col : colMeta t)</div><div>                               (acc : xml form [] (map snd rest)) =></div><div>                  <xml></div><div>                    <li> {cdata col.Nam}: {col.WidgetPopulated [nm] v}</li></div><div>                    {useMore acc}</div><div>                  </xml>)</div><div>              <xml/></div><div>              M.fl fs.Tab M.cols}</div><div>                 (*   ^^^  *)</div><div>            <submit action={save}/></div><div>          </form></body></xml></div><div><br></div><div>What if we change these two occurrences of the (upper-case) identifier, from `Tab` to `Tabx` - leaving the lower-case identifier `tab` (which also occurs many times elsewhere in the module) unchanged?</div><div><br></div><div>The code no longer compiles! It gives the following error:</div><div><br></div><div>crud.ur:126:32: (to 126:70) Error in final record unification</div><div><br></div><div>Can't unify record constructors</div><div>   Have: </div><div>[Distinct = bool, </div><div>  From =</div><div>   sql_from_items ([])</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols]),</div><div>                                                                        </div><div>  Where =</div><div>   sql_exp</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([]) ([]) bool, </div><div>  GroupBy =</div><div>   sql_subset</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols]),</div><div>                                                                        </div><div>  Having =</div><div>   sql_exp</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([]) bool, </div><div>  SelectFields =</div><div>   sql_subset</div><div>    ([Tab = (map (fn t :: (Type * Type) => t.1) M.cols) ++ [Id = int]])</div><div>    ([Tab = map (fn t :: (Type * Type) => t.1) M.cols]), </div><div>  SelectExps = {}]</div><div>   Need: </div><div>[Distinct = bool, </div><div>  From =</div><div>   sql_from_items ([])</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols]),</div><div>                                                                        </div><div>  Where =</div><div>   sql_exp</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([]) ([]) bool, </div><div>  GroupBy =</div><div>   sql_subset</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols]),</div><div>                                                                        </div><div>  Having =</div><div>   sql_exp</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([]) bool, </div><div>  SelectFields =</div><div>   sql_subset</div><div>    ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div>    ([Tabx = map (fn t :: (Type * Type) => t.1) M.cols]), </div><div>  SelectExps = {}]</div><div>  Field:  #SelectFields</div><div><br></div><div>Value 1: </div><div>sql_subset</div><div> ([Tab = (map (fn t :: (Type * Type) => t.1) M.cols) ++ [Id = int]])</div><div> ([Tab = map (fn t :: (Type * Type) => t.1) M.cols])</div><div><br></div><div>Value 2: </div><div>sql_subset</div><div> ([Tab = ([Id = int]) ++ map (fn t :: (Type * Type) => t.1) M.cols])</div><div> ([Tabx = map (fn t :: (Type * Type) => t.1) M.cols])</div><div><br></div><div>Can't unify record constructors</div><div><br></div><div>Have:  [Tab = map (fn t :: (Type * Type) => t.1) M.cols]</div><div>Need:  [Tabx = map (fn t :: (Type * Type) => t.1) M.cols]</div><div><br></div><div>$ </div><div><br></div><div>The above suggests that there is some sort of "relationship":</div><div><br></div><div>BETWEEN:</div><div><br></div><div>(1) the *lower-case* identifier `tab`:</div><div><br></div><div>  - whose *type* is *declared* (in the parameter signature of the declaration of Crud.Make in crud.urs and crud.ur) as follows:</div><div><br></div><div>      table tab : ([Id = int] ++ map fst cols)</div><div><br></div><div>  - and whose *value* is *defined* in (eg) crud1.ur, in the argument in the call to Crud.Make, as follows:</div><div><br></div><div>      val tab = t1</div><div><br></div><div>  ... where (eg) the table `t1` (defined earlier in crud1.ur) is in lexical scope:</div><div><br></div><div>      table t1 : {Id : int, A : int, B : string, C : float, D : bool}</div><div><br></div><div>VERSUS:</div><div><br></div><div>(2) the *upper-case* identifier `Tab` - which appears to be:</div><div><br></div><div>  - (a) a *field name* whose presence is being "asserted", or</div><div><br></div><div>  - (b) (perhaps?) a *pattern* being assigned to in some sort of record-level or type-level pattern-matching - in the "type declaration" - or "assertion?" or "pattern-matching"?? - provided for `fso` in the `case` statement (*after* `fso` was "created", by the way):</div><div><br></div><div>      case fso : (Basis.option {Tab : $(map fst M.cols)}) of ... </div><div><br></div><div>---</div><div><br></div><div>I have several questions arising from the above:</div><div><br></div><div>(1) What is this relationship between identifier `tab` and identifier `Tab` here? </div><div><br></div><div>One appears to refer to a table, the other appears to be a field.</div><div><br></div><div>Is there some sort of pattern-matching or assertion or assignment going on between them?</div><div><br></div><div><br></div><div>(2) This compile error seems to indicate that identifier `tab` and identifier `Tab` need to be the *same* (except for upper-case versus lower-case). </div><div><br></div><div>Is this true? </div><div><br></div><div>If so, why? </div><div><br></div><div>(2.1) Is it true that an Ur/Web database application can be associated with exactly *one* SQL database (mentioned in the .urp file)? </div><div><br></div><div>(2.2) If (2.1) is true, then is there some relationship:</div><div><br></div><div>BETWEEN:</div><div><br></div><div>- the namespace of unique (upper-case) *field names* defined at the "top level" of an Ur/Web program;</div><div><br></div><div>VERSUS </div><div><br></div><div>- the namespace of unique (lower-case) identifiers assigned to *table names* - in statements such as:</div><div><br></div><div>  table t1 : {Id : int, A : int, B : string, C : float, D : bool}<br></div><div><br></div><div>which generate CREATE TABLE statements in the *.sql script (with names optionally mangled with a "uw_" prefix) for the associated SQL database mentioned in the .urp file?<br></div><div><br></div><div>(3) What does the syntax:</div><div><br></div><div>  {Tab : $(map fst M.cols)}</div><div><br></div><div>ie:</div><div><br></div><div>  { ... : ... }</div><div><br></div><div>mean?</div><div><br></div><div><br></div><div>(3.1) Is the syntax `{ ... : ... }` an instance of the following kind-level production in section 4.2, page 15 of the manual:</div><div><br></div><div>  Kinds κ ::=</div><div>    ...</div><div>    {κ}    type-level records</div><div>    ...</div><div><br></div><div>Question (3.1.1) If so, is this perhaps somehow combined with some *other* production(s) in the present case, to yield (in the present example):</div><div><br></div><div>  {Tab : $(map fst M.cols)}</div><div><br></div><div><br></div><div>(3.1.2) Could the other production being combined here be: </div><div><br></div><div>  Kind ::= Type</div><div><br></div><div>(also from Section 4.2, page 15)<br></div><div><br></div><div>in this case instantiating ``Type`` as:</div><div><br></div><div>  Tab : $(map fst M.cols)</div><div><br></div><div>?</div><div><br></div><div>Question (3.2) Is the above syntax `{ ... : ... }` as used eg in:</div><div><br></div><div>{Tab : $(map fst M.cols)}<br></div><div><br></div><div>related to the "table-definition syntax" (seen frequently in the examples - but never actually explicitly described "as such" in the manual), eg:</div><div><br></div><div>  table t1 : {Id : int, A : int, B : string, C : float, D : bool}</div><div><br></div><div>?<br></div><div><br></div><div><br></div><div>(3.3) Is this syntax `{ ... : ... }`  as used eg in:</div><div><br></div><div>  {Tab : $(map fst M.cols)}</div><div><br></div><div>perhaps also somehow related to the following fragment of code in basis.urs - in particular, the section underscored using the comment `(*   ^^^  *)`:</div><div><br></div><div><a href="http://hg.impredicative.com/urweb/file/010ce27228f1/lib/ur/basis.urs#l488">http://hg.impredicative.com/urweb/file/010ce27228f1/lib/ur/basis.urs#l488</a></div><div><br></div><div>val sql_field : otherTabs ::: {{Type}} -> otherFields ::: {Type}</div><div> -> fieldType ::: Type -> agg ::: {{Type}}</div><div> -> exps ::: {Type}</div><div> -> tab :: Name -> field :: Name</div><div> -> sql_exp</div><div>        ([tab = [field = fieldType] ++ otherFields] ++ otherTabs)</div><div>    (*  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  *)</div><div>        agg exps fieldType</div><div><br></div><div><br></div><div>(4) Finally, the manual (towards the bottom of page 19) states:</div><div><br></div><div>  A declaration </div><div><br></div><div>    table x : {(c = c,)∗} </div><div><br></div><div>  is elaborated into </div><div><br></div><div>    table x : [(c = c,)∗]</div><div><br></div><div>However, a *different* syntax is commonly seen in the "table declarations" frequently used in the demos - ie, in the demos, the "copulas" are `:` not `=`, eg:</div><div><br></div><div>  table t1 : {Id : int, A : int, B : string, C : float, D : bool}</div><div><br></div><div>(4.1) What does the following syntax in the manual (using `=` not `:`) refer to:</div><div><br></div><div>  table x : {(c = c,)∗}</div><div>  table x : [(c = c,)∗]</div><div><br></div><div>(4.2) Are the any examples of its use?</div><div><br></div><div><br></div><div>Thanks for any help!</div><div><br></div><div>###</div><div><br></div><div><br></div></div>