【问题标题】:How to unbox F# tuple object where tuple has arbitrary number of elements如何在元组具有任意数量的元素的情况下拆箱 F# 元组对象
【发布时间】:2020-07-30 19:13:30
【问题描述】:

将列表转换为元组使用 how-can-i-convert-between-f-list-and-f-tuple

添加let a' = Array.map box a 由于 MakeTuple 需要 obj 数组, 和let t = unbox<float*float*float> o 获取元组。

例子:

let a = List.toArray [1.0; 2.0; 3.0]
let types = a |> Array.map (fun o -> o.GetType())
let tupleType = Microsoft.FSharp.Reflection.FSharpType.MakeTupleType types
let a' = Array.map box a
let o = Reflection.FSharpValue.MakeTuple (a' , tupleType)
let t = unbox<float*float*float> o

这适用于长度为 3 的浮点列表。根据需要返回 val t : float * float * float = (1.0, 2.0, 3.0)

但我想转换任意长度的列表。

从列表转换为 obj 适用于任意长度(和类型),我的问题是拆箱。

【问题讨论】:

    标签: f#


    【解决方案1】:

    您使用一个有点武断的例子来激发这个问题。我认为你想要这个的实际动机比较棘手,最好知道这个实际动机是什么 - 因为它可能有助于给出一个好的答案。

    首先,如果您想使用任意长度的元组,您可能不应该使用元组。 F# 元组是固定的(静态已知的)长度。它们的其他用途会很麻烦。 (与某些动态语言中元组更频繁地用于任意长度数据的情况不同。)其次,如果您在编译时不知道类型,我不确定您想通过拆箱实现什么。

    根据您的实际动机,有一个技巧可能会有所帮助。诀窍是通过反射调用泛型方法,将未装箱的值传递给它。

    如果我们假设您的元组的所有元素都具有相同的类型,您可以将它们视为一个数组(未装箱但通用值):

    type Helper = 
      static member Process<'T>(data:'T[]) = 
        typeof<'T>.Name
    

    现在您可以使用反射调用Helper.Process

    open Microsoft.FSharp.Reflection
    
    let a = (1., 2.)
    
    let tys = FSharpType.GetTupleElements(a.GetType())
    for ty in tys do if ty <> tys.[0] then failwith "All types must be the same"
    
    let flds = FSharpValue.GetTupleFields(a)
    let arr = System.Array.CreateInstance(tys.[0], flds.Length)
    System.Array.Copy(flds, arr, flds.Length)
    typeof<Helper>.GetMethod("Process")
      .MakeGenericMethod([| tys.[0] |]).Invoke(null, [| arr |] )
    

    这将返回"Double",因为当通过反射调用时,'T 的类型将是Double,因此您实际上得到的是未装箱的值。

    在极少数情况下,这样的东西很有用,但我猜你实际上并不需要它,相反,你最好用不同的方式来表示你的数据。

    【讨论】:

    • 实际动机是我用来学习 F# 的优化算法 (Nelder-Mead link)。我使用 float list 作为 Vertex 类型,然后在评估目标函数时使用 tuple,请参阅link。我现在可以跳过元组步骤,使目标成为 Vertex 的函数,从而适应目标函数。目标函数会有所不同,但我会在编译时知道。
    • 我尝试过修改 Triple link。它变得复杂,所以我回到使用浮动列表link。到目前为止只有 2D,但稍后将用于 6D 和 20D 顶点。浮动清单会是最佳选择吗? @TomasPetricek
    猜你喜欢
    • 1970-01-01
    • 2021-12-05
    • 2019-03-06
    • 2013-10-24
    • 1970-01-01
    • 2019-08-13
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多