[Ur] Building site templates

austin seipp as at hacks.yi.org
Tue Dec 6 17:23:26 EST 2011


If you change the type of 'template' in common.ur to use 'xbody'
instead of xml, then the errors point you in the more correct
direction. In line 25 of common.ur you have this:

<a link={template (Some "hi")}><img src="/images/reallybigtalkslogo.gif" /></a>

'template' is the function you are defining, which is fine by itself
(recursion is nice,) but you're not fully applying the arguments and
so the types mismatch. Partially applied, the expression 'template
(Some "hi")' has a type more like 'xbody -> transaction page'. The
antiquotation for a link needs a 'fully applied' page handler that it
can link to. So you need some body to apply to make the function's 2nd
argument to make it typecheck.

However, substituting the above with 'template (Some "hi")
<xml></xml>' for example, you get another compiler error:

"Input to exported function 'Common/template' involves one or more
types that are disallowed for page handler inputs: Basis.xml"

Which is reasonable as hell from a safety standpoint, because
otherwise Bad Things could happen if you could just give the page
handler arbitrary XML to input in a page.

Looking at your code, what you probably want is to make your sidebar
its own abstract data type (probably behind its own module, giving the
user only an opaque 't' type, not letting them see the internal
representation.) You should have functions over this which could
render them to HTML fragments (basically a function of type 'Sidebar.t
-> xbody'.)

Because sidebars are generally something that you're going to have
control over, rather than recompile your application willy nilly, the
easiest thing would likely be to structure the content into a SQL
table. The interface you export through the module however does not
need to expose any internals - it can just have a signature file like.

A good example of doing something vaguely similar to this is the
included 'Ref' demo, online here:

http://impredicative.com/ur/demo/

Some other general tips:

1. The included HTML tags in the standard library have a notion of
'context' - certain tags are only valid in certain contexts. A 'head'
tag may only appear inside the overall document, while a 'a' tag must
be inside the <body> for example. Another example is tables: table
tags (like <tr>) can only appear inside the scope of a '<table>'.
Static type checking is used to enforce proper contexts.

2. 'xml' is a constructor which refers to XHTML documents, generally,
those are the things inside the <xml> tag.

3. 'xhtml' is the constructor which references the entire document
residing in the <html> tag - including all the body tags, head tags,
etc. 'page' is actually an alias for a fully applied variant of
'xhtml' - so a 'page' is just a valid HTML page.

4. 'xbody' is the constructor which references tags which appear
*inside* the body tag - normally the place you would render things for
people to view.

5. All the syntactic sugar for XHTML tags dissolves to the
corresponding *value* inside the basis library. Tag attributes desugar
directly to record field names. So '<a link={...}>' actually desugars
to a *value* of type 'bodyTag ([Link = transaction page, Href = url,
...])' What this *means* is that the 'link' attribute must be a
effectful transaction which returns a page, and the 'href' attribute
must be of type 'url'. Looking at the tag in the basis library lets
you know what attributes it supports.

Keeping this in mind, check out some of the standard library here:
http://hg.impredicative.com/urweb/file/deeeb036c8ed/lib/ur/basis.urs

The basis signature file outlines all the included tags the compiler
supports. Browsing it may be hard at first but as you begin to get
more comfortable with Ur records, you should be able to get an
intuition about what (some) of the error messages mean.

As for the inference errors: they are bad, but they generally point
you around the code at fault as they did here, if you go by the error
line #s and look around. You'll get intuition for the actual errors
(in all their verbosity) as you keep going forward. The compiler does
tricky things for its unification algorithm to work in the presence of
the powerful Ur type system, so sometimes the inferred types can seem
confusing as an example.

On Tue, Dec 6, 2011 at 3:33 PM, James Parker <jp at jamesparker.me> wrote:
> I've tried xml, body, and xhtml. Is there some other type I can try? If I simply define sidebar inside template, the project will compile and run correctly.
>
> The source is available here if it's helpful:
>
> https://github.com/jprider63/UMDTalks
>
> Here's the full error message:
>
> /home/james/Projects/UMDTalks/common.urs:4:32-4:35: Wrong kind
> Constructor:  Basis.xml
>  Have kind:  {Unit} -> {Type} -> {Type} -> Type
>  Need kind:  Type
> Incompatible kinds
> Kind 1:  {Unit} -> {Type} -> {Type} -> Type
> Kind 2:  Type
> /home/james/Projects/UMDTalks/common.ur:10:0-50:0: Constructor unification failure in signature matching:
>  Have:
> val template :
>  ((Basis.option Basis.string) ->
>   ((Basis.xml ([#Body = ()]) <UNIF:U0::{Type}> <UNIF:U2::{Type}>) ->
>     <UNIF:F::Type -> Type>
>      (Basis.xml ([#Html = ()]) <UNIF:U0::{Type}> <UNIF:U2::{Type}>)))
>  Need:
> val template :
>  ((Basis.option Basis.string) ->
>   (Basis.xml ->
>     Basis.transaction (Basis.xml ([#Html = ()]) ([]) ([]))))
> Con 1:
> ((Basis.option Basis.string) ->
>  ((Basis.xml ([#Body = ()]) <UNIF:U0::{Type}> <UNIF:U2::{Type}>) ->
>    <UNIF:F::Type -> Type>
>     (Basis.xml ([#Html = ()]) <UNIF:U0::{Type}> <UNIF:U2::{Type}>)))
> Con 2:
> ((Basis.option Basis.string) ->
>  (Basis.xml ->
>    Basis.transaction (Basis.xml ([#Html = ()]) ([]) ([]))))
> Incompatible constructors
> Have:  Basis.xml ([#Body = ()]) <UNIF:U0::{Type}> <UNIF:U2::{Type}>
> Need:  Basis.xml
> /home/james/Projects/UMDTalks/umdtalks.ur:33:1-34:38: Unification failure
> Expression:
> fn sidebar : Basis.xml =>
>  Common.template (Some [Basis.string] "test") sidebar
>  Have con:
> (Basis.xml -> Basis.transaction (Basis.xml ([#Html = ()]) ([]) ([])))
>  Need con:
> ((Basis.xml (([#Body = ()]) ++ <UNIF:U10::{Unit}>) <UNIF:U2::{Type}>
>   ([])) -> <UNIF:S::Type -> Type> <UNIF:U::Type>)
> Incompatible constructors
> Have:  Basis.xml
> Need:
> Basis.xml (([#Body = ()]) ++ <UNIF:U10::{Unit}>) <UNIF:U2::{Type}>
>
> I've been finding it somewhat difficult to understand what the error messages are looking for. Are the type inferencing messages a result of the wrong signature type?
>
> Thanks,
>
> JP
>
> On Dec 6, 2011, at 8:40 AM, Adam Chlipala wrote:
>
>> James Parker wrote:
>>>         title'<- return (case title of
>>>                 | None =>  "UMDTalks"
>>>                 | Some t =>  String.append t " - UMDTalks"
>>>
>>
>> Here I would recommend the infix operator [^] instead of [String.append].
>>
>>> My current function signature is:
>>>
>>> val template : option string ->  xml ->  transaction page
>>>
>>> I believe the problem is in the signature. I guess what is the proper type for the second parameter?
>>>
>>
>> You probably want [xbody] instead of [xml].  You can look in lib/ur/basis.urs to see the kinds of all the built-in constructors.
>>
>> _______________________________________________
>> Ur mailing list
>> Ur at impredicative.com
>> http://www.impredicative.com/cgi-bin/mailman/listinfo/ur
>
>
> _______________________________________________
> Ur mailing list
> Ur at impredicative.com
> http://www.impredicative.com/cgi-bin/mailman/listinfo/ur



-- 
Regards,
Austin



More information about the Ur mailing list