F#结构元组与BCL元组类型 [英] F# structural tuples versus BCL Tuple types

查看:124
本文介绍了F#结构元组与BCL元组类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在F#中,您可以按以下方式定义first函数:

In F# you can define a first function as follows:

let first (x, y) = x

您可以这样称呼它:

first (1, 2)

您还可以根据BCL Tuple类型定义相同的功能:

You can also define the same function in terms of the BCL Tuple type:

let first (t:Tuple<_, _ >) = t.Item1

但是,您不能使用以前的语法来调用它,否则会出现以下错误:

However, you cannot call it using the prior syntax, or you will get the following error:

error FS0001: The type ''c * 'd' is not compatible with the type 'Tuple<'a,'b>'

相反,您必须执行以下操作:

Instead, you have to do the following:

first (Tuple<_,_>(1, 2))

这很奇怪,因为在任何一种情况下,编译的F#代码似乎都使用Tuple表示其参数.那么,为什么F#编译器告诉我这些类型不兼容?

This is strange, since compiled F# code does seem to use Tuple to represent its parameters in either case. So why is the F# compiler telling me that the types are not compatible?

为什么这很重要?好吧,基本上,我想编写一个带有重载的方法,该重载支持任意长度的元组.对于F#的语法元组,这是不可能的,因为必须事先知道参数的确切数量.但是,使用BCL Tuple类型似乎确实可行,因为这些类型使用TRest技巧来允许任意长度的元组.不幸的是,如果我用这种方式编写重载,那么它们将无法使用F#语法元组,这是最终目标.

Why does any of this matter? Well, basically I want to write a method with overloads supporting a tuple of arbitrary length. This is impossible with F#'s syntactic tuples, since the exact number of arguments must be known in advance. However, it does seem possible by using the BCL Tuple types, because those use the TRest trick to allow tuples of arbitrary length. Unfortunately, if I write my overloads this way, then they won't work with F# syntactic tuples, which is the ultimate goal.

所以我的问题是:为什么语法元组和BCL元组不兼容?而且,在F#中是否有任何可以对任意长度的元组进行操作的编写函数和/或方法的示例?

So my question is: why aren't syntactic tuples and BCL tuples compatible? And also, are there any examples of writing functions and/or methods that operate on arbitrary-length tuples in F#?

特定的应用程序处理我正在编写的基于类型推断的二进制解析库.您可以在此处查看代码.您可以看到元组有许多重载,但是我不想将它们扩展到某个幻数.

The specific application deals with a type inference-based binary parsing library I'm writing. You can view the code here. You can see the many overloads that I have for tuples, but I don't want to extend them out to some magic number.

推荐答案

通常的F#规范进行救援:

as usual F# spec to the rescue:

6.3.2元组表达式

expr1,...,exprn形式的表达式是一个元组表达式.例如:

An expression of the form expr1, ..., exprn is a tuple expression. For example:

let three = (1,2,"3")
let blastoff = (10,9,8,7,6,5,4,3,2,1,0)

对于新类型ty1…tyn,表达式具有类型(ty1 * ... * tyn),并且使用初始类型tyi检查每个表达式ei.

The expression has the type (ty1 * ... * tyn) for fresh types ty1 … tyn, and each individual expression ei is checked using initial type tyi.

元组类型和表达式转换为F#库类型家族的应用程序,该系统名为System.Tuple.元组类型ty1 * ... * tyn的翻译如下:

Tuple types and expressions are translated into applications of a family of F# library types named System.Tuple. Tuple types ty1 * ... * tyn are translated as follows:

  • 对于n< = 7,详细形式为Tuple<ty1,...,tyn>.
  • 对于较大的n,元组类型是附加的F#库类型System.Tuple<_>的应用程序的简写,如下所示:
  • 对于n = 8,详细形式为Tuple<ty1,...,ty7,Tuple<ty8>>.
  • 对于9< = n,详细形式为Tuple<ty1,...,ty7,tyB>,其中tyB是类型(ty8 ... tyn)的转换形式.
  • For n <= 7 the elaborated form is Tuple<ty1,...,tyn>.
  • For larger n, tuple types are shorthand for applications of the additional F# library type System.Tuple<_> as follows:
  • For n = 8 the elaborated form is Tuple<ty1,...,ty7,Tuple<ty8>>.
  • For 9 <= n the elaborated form is Tuple<ty1,...,ty7,tyB> where tyB is the converted form of the type (ty8 ... tyn).

元组表达式(expr1,...,exprn)的翻译如下:

Tuple expressions (expr1,...,exprn) are translated as follows:

  • 对于n< = 7,其详细形式为new Tuple<ty1,…,tyn>(expr1,...,exprn).
  • 对于n = 8的精细形式new Tuple<ty1,…,ty7,Tuple<ty8>>(expr1,...,expr7, new Tuple<ty8>(expr8).
  • 对于9< = n,其精细形式new Tuple<ty1,...ty7,ty8n>(expr1,..., expr7, new ty8n(e8n)其中ty8n是类型(ty8 * ... * tyn),而expr8n是表达式的精细形式 expr8,...,exprn.
  • For n <= 7 the elaborated form new Tuple<ty1,…,tyn>(expr1,...,exprn).
  • For n = 8 the elaborated form new Tuple<ty1,…,ty7,Tuple<ty8>>(expr1,...,expr7, new Tuple<ty8>(expr8).
  • For 9 <= n the elaborated form new Tuple<ty1,...ty7,ty8n>(expr1,..., expr7, new ty8n(e8n) where ty8n is the type (ty8*...* tyn) and expr8n is the elaborated form of the expression expr8,..., exprn.

当被视为静态类型时,元组类型与其编码形式不同.但是,元组值和类型的编码形式在F#类型系统中通过运行时类型可见.例如,typeof等效于typeof<System.Tuple<int,int>>,而(1,2)具有运行时类型System.Tuple<int,int>.同样,(1,2,3,4,5,6,7,8,9)的运行时类型为Tuple<int,int,int,int,int,int,int,Tuple<int,int>>.

When considered as static types, tuple types are distinct from their encoded form. However, the encoded form of tuple values and types is visible in the F# type system through runtime types. For example, typeof is equivalent to typeof<System.Tuple<int,int>> , and (1,2) has the runtime type System.Tuple<int,int>. Likewise, (1,2,3,4,5,6,7,8,9) has the runtime type Tuple<int,int,int,int,int,int,int,Tuple<int,int>>.

注意:将元组添加到.NET 4.0中的BCL之前,F#使用了FSharp.Core dll中定义的System.Tuple类型

NOTE: prior to adding tuples to BCL in .NET 4.0 F# used System.Tuple type defined in FSharp.Core dll

我想您处理具有任意大小的元组的唯一方法是先进行构造和解构,然后再使用Microsoft.FSharp.Reflection.FSharpType\FSharpValue

I guess the only way for you to deal with tuples having arbitrary size is to resort to constructing and deconstructing then with functions from Microsoft.FSharp.Reflection.FSharpType\FSharpValue

这篇关于F#结构元组与BCL元组类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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