[Ur] typechecker rejects form handler

Adam Chlipala adamc at csail.mit.edu
Tue Jan 7 13:18:25 EST 2014

On 01/07/2014 12:54 PM, Sergey wrote:
> On 05.01.2014 22:37, Adam Chlipala wrote:
>> More precisely, you'll run into trouble if you cause multiple 
>> specializations of a function that defines local functions that need 
>> to have URIs assigned to them!
> But I've experimented with moving function `validator' to a global 
> scope, like this:
> fun validator (fview : int -> url) (ferr : string -> url) (i:int) 
> (s:{Text:string}) : transaction page =  (* the same code *)
> fun form (fview : int -> url) (ferr : string -> url) (i:int) : 
> transaction xbody =
>   return
> <xml>
> <form>
> <textarea{#Text}/>
> <br/>
> <submit action={validator fview ferr i}/>
> </form>
> </xml>
> The error remains the same.

You're right.  I shouldn't have brought local functions into the 
picture.  What actually matters is which functions, local or global, are 
specialized to different argument lists, while also needing URLs assigned.

>>> Do you plan to introduce some kind of automatic names generator for 
>>> cases
>>> like this one?
>> No, I advise folks to use functors for such cases.
> Functors have a weak point: looks like they don't support recursive 
> declarations. Imagine the following use-case: An application has 
> several different views, each view has a small login/password form in 
> it's upper-right corner. Developer wants to improve the usability of 
> this application by redirecting users back to the view they were at 
> the moment they filled up the form.

I suggest passing URLs instead of functions for this case, avoiding any 
need for functors.

> I am sure that most of the people would try to use a basic functional 
> trick here:
> (* Version 1 *)
> fun validate_and_apply f = return {}
> fun handler u f = validate_and_apply f ; redirect u
> fun form (u:url) : transaction xbody = reutrn <xml><form>...<submit 
> action={handler u}/></form></xml>
> fun viewA (idx:int) = template ( f<- form (url (viewA idx)); return 
> <xml>{f}</xml>)
> fun viewB (idx:int) = template ( f<- form (url (viewB idx)); return 
> <xml>{f}</xml>)
> ...
> The "Input to exported function 'FormBug3/handler' involves one or 
> more types that are disallowed for page handler inputs: Basis.url" 
> will appear.

You can get around this issue by using type [string] instead of [url].  
Use [show] to convert [url] to [string], then use [bless] to convert 
back.  I've done this before for various sites.  You can even use 
[Basis.currentUrl] to get the current URL, without forcing each caller 
of the redirecting function to construct the URL explicitly.

Note that this is _not_ a case of unjustifiable draconian behavior by 
the compiler, since [bless] will do run-time checking that URLs follow 
the policy you've configured in .urp files.

More information about the Ur mailing list