This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 5696 - [XQuery 1.1] Feature request to aid static typing
Summary: [XQuery 1.1] Feature request to aid static typing
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XQuery 3.0 (show other bugs)
Version: Recommendation
Hardware: All All
: P2 enhancement
Target Milestone: ---
Assignee: Michael Dyck
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-05-16 15:47 UTC by Nick Jones
Modified: 2009-12-08 18:10 UTC (History)
3 users (show)

See Also:


Attachments

Description Nick Jones 2008-05-16 15:47:05 UTC
We've been looking at static typing in the new functx tests, and have come across some queries which we are unable to rewrite so they type check, for example:

declare function functx:value-except
  ( $arg1 as xs:anyAtomicType* ,
    $arg2 as xs:anyAtomicType* )  as xs:anyAtomicType* {

  distinct-values($arg1[not(.=$arg2)])
 } ;

because fs:equal is not defined for all pairs of atomic types in xs:anyAtomicType an XPTY0004 is thrown.

Obviously, separate value-except-type functions could be defined for arguments of each atomic type. But we can't think of any other way to rewrite such a function to type check. We propose two options to "fix" this problem.

Option 1
--------

Recall the general comparisons expand (roughly) out to to the form:

some $x in $arg1 satisfies
  some $y in $arg2 satisfies
    $x op $y

So currently the queries

(1, "foo") = "foo"

and

("foo", 1) = "foo"

may return true or XPTY0004, depending on the order in which
the implementation happens to process the query.

We'd like to propose that if the value comparison used in the 
expansion of the general comparison is not defined for the input
types, then the result is false.

Thus

(1, "foo") = "bar"

would return false.


Option 2
--------

Add generics.

declare function functx:value-except
  ( $arg1 as type(T) <: xs:anyAtomicType* ,
    $arg2 as T )  as T {
  distinct-values($arg1[not(.=$arg2)])
 } ;

This of course would open up a need for a whole host of 
type-describing syntax, e.g. to specify subtype releationships,
type unions etc.

Option 3
--------

We could fix this query by using XQuery 1.1 try/catch.

".=$arg2" would have to be expanded out manually to "some" expressions
with a try/catch to return "false" when the XPST0004 is raised.

This would be rather clumsy.

Option 4
--------

Define union, except, intersect functions/operators which work nicely
with xs:anyAtomicType* input.  Obviously this doesn't fix the general case.

Our guess is that option 1 will make a wider variety of queries run in 
static typing mode, but introducing a breaking change with XQuery 1.0
might be unacceptable.

Option 2 might be nice but might require a fair amount of work by the 
Working Group.
Comment 1 Michael Kay 2008-05-16 17:53:24 UTC
Presumably the issue also affects our own version of this function in

http://www.w3.org/TR/xpath-functions/#value-except

I've often argued that a=b should return false if a and b are of incomparable types, but I've always lost the argument to those who prefer the diagnostic power of raising an error. There are arguments both ways.

A possible circumvention is to use one of the functions that does allow comparison of incomparables, for example index-of(), distinct-values(), or deep-equal(). If you don't want (a eq b) to fail, you can always write it as deep-equal(a, b).
Comment 2 Michael Dyck 2008-10-25 18:51:52 UTC
(In reply to comment #0)
>
> Option 3
> --------
> 
> We could fix this query by using XQuery 1.1 try/catch.
> 
> ".=$arg2" would have to be expanded out manually to "some" expressions
> with a try/catch to return "false" when the XPST0004 is raised.
> 
> This would be rather clumsy.

I don't understand why you'd need to expand to 'some' expressions.
Why not just replace
    .=$arg2
with
    try { .=$arg2 } catch err:XPTY0004 { false() }

Or, for better encapsulation, replace it with
    my-equal(., $arg2)
where 'my-equal' has the semantics that Option 1 would give to '=':
    declare function my-equal(...) as boolean()
    {
        try { $arg1 = $arg2 } catch err:XPTY0004 { false() }
    }
Comment 3 Tim Mills 2008-10-28 13:00:12 UTC
Haskell has type classes, described at 

http://www.haskell.org/tutorial/classes.html 

which seem like a very well designed way of describing the sort of constraints on types suggested by Option 2.  This might be a useful addition to XQuery.

As an off-topic aside, I'm personally a bit wary of try ... catch.  I've got a horrible feeling I'm turning into a functional purist.  Even element constructors make me feel queazy :)
Comment 4 Michael Dyck 2009-12-08 18:09:44 UTC
At today's Working Group meeting, Nick Jones (the original poster) reviewed this bug, and said that try/catch allowed an adequate solution to the problem. Therefore, I am marking this bug Resolved-Fixed, and also Closed.