F #: overload functions

My question is somewhat related to this - Functions with generic parameter types - but I can't figure out how to do what I want.

I want to define the descendants function to wrap the call for the descendants in various C # classes as follows:

descendant name (xDocument: XDocument) = xDocument.Descendants name

let descendant name (xElement: XElement) = xElement.Descendants name

This approach does not work, because we have a duplicate definition of "descendants".

I thought it was possible to use a built-in function and statically allow parameters to define the following method for this:

let inline descendants name (xml : ^x when ^x : (member Descendants : XName -> seq<XElement>)) = xml.Descendants name 

But I get this error when trying to do this:

Search for an object of an indefinite type based on information up to this point in the program. Type annotations may be required up to this point in the program to limit the type of object. This allows you to allow the search.

Is there a way so that I can write this second function to accomplish what I need?

+6
f #
Feb 14 2018-10-14
source share
2 answers

Generally speaking, I think that hat types such as ^x can be used too much (at least judging by the number of questions about them in SO). This is a powerful feature, but it was designed primarily to solve problems with general arithmetic. I think they can make F # programs unnecessary.

If you work only with XDocument and XElement , then the answer is quite simple, because you can use XContainer , which is their common base class, and has a Descendants method:

 let descendants name (xml:XContainer) = xml.Descendants(name) // Both of these will work fine descendants (XName.Get "foo") xd descendants (XName.Get "foo") xe 

If you cannot find a common base class, you can, of course, use the ^a type, but you can also use the usual overload, which is possible in F #, but only works for members of the object type:

 type Xml = static member Descendants(name, x:XDocument) = x.Descendants(name) static member Descendants(name, x:SomeOtherClass) = x.SomeOtherDescendants(name) // The usage looks like this: Xml.Descendants(XName.Get "foo", xd) Xml.Descendants(XName.Get "foo", new SomeOtherClass()) 

(Since you referred to a question with an answer that already shows that overloading works with members, this is probably not new to you, but may be useful to others who find this question in the future).

+14
Feb 14 '10 at 13:30
source share

The code below compiles (and points to the syntax needed to call the static member constraint functions).

 open System.Xml.Linq let descendants1 name (xDocument:XDocument) = xDocument.Descendants name let descendants2 name (xElement:XElement) = xElement.Descendants name let inline descendants name (xml : ^x when ^x : (member Descendants : XName -> seq<XElement>)) = (^x : (member Descendants : XName -> seq<XElement>) (xml,name)) let xd = XDocument.Load("http://www.somexml.com") let ds = descendants (XName.op_Implicit "foo") xd let xe = XElement.Load("http://www.somexml.com") let eds = descendants (XName.op_Implicit "foo") xe 
+4
Feb 14 '10 at 13:12
source share



All Articles