F#:重载函数 [英] F#: Overloading functions

查看:71
本文介绍了F#:重载函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题与此相关-具有通用参数类型的函数-但是我不太想知道如何做自己想做的事.

我想定义一个'descendants函数',以便在各种C#类上包装对'Descendants'的调用,像这样:

让子孙的名字(xDocument:XDocument)= xDocument.Descendants的名字

让后代名称(xElement:XElement)= xElement.后代名称

这种方法行不通,因为我们对后裔"有重复的定义.

我认为可以使用内联函数并静态解析参数来定义以下方法来实现此目的:

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

但是尝试执行此操作时出现此错误:

根据此程序点之前的信息查找不确定类型的对象.在此程序指向之前可能需要类型注释,以约束对象的类型.这样可以解决查找问题.

有没有一种方法可以编写第二个函数来完成我想做的事情?

解决方案

一般来说,我认为帽子类型(例如^x)的使用可能过多(至少从关于所以).它是一个强大的功能,但实际上它的设计主要是为了解决泛型运算法则的问题.我认为它们可以使F#程序不必要地变得复杂.

如果仅使用XDocumentXElement,则答案非常简单,因为您可以使用XContainer,这是它们的常见基类,并且具有Descendants方法:

let descendants name (xml:XContainer) = xml.Descendants(name)

// Both of these will work fine
descendants (XName.Get "foo") xd
descendants (XName.Get "foo") xe

如果找不到通用的基类,那么当然可以使用^a类型,但是您也可以使用常规重载,这在F#中是可能的,但仅适用于对象类型成员:

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())

(由于您引用的问题的答案已经表明成员可以重载,所以这对您来说可能不是什么新鲜事物.但这对将来会发现此问题的其他人可能很有用). /p>

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

I want to define a 'descendants function to wrap the call to 'Descendants' on various C# classes like so:

let descendants name (xDocument:XDocument) = xDocument.Descendants name

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

This approach doesn't work because we have a duplicate definition of 'descendants'.

I thought it would be possible to make use of the inline function and statically resolve parameters to define the following method to do this instead:

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

But I'm getting this error when trying to do that:

Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.

Is there a way that I can write that second function to do what I want?

解决方案

Generally speaking, I think that hat-types such as ^x are being maybe used too much (at least, judging by the number of questions about them at SO). It is a powerful feature, but it was really designed mainly to solve problems with generic arithmethic. I think they can make F# programs unnecesarily complicated.

If you're working just with XDocument and XElement, then the answer is pretty simple, because you can use XContainer which is their common base class and has the 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, then you can of course use ^a type, but you could also use normal overloading, which is possible in F#, but works only for object-type members:

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 referenced a question with an answer which already shows that overloading works with members, this probably isn't anything new for you. But it may be useful to others who'll find this question in the future).

这篇关于F#:重载函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆