有没有办法在F#List和F#Tuple之间进行转换?
例如:
[1;2;3] -> (1,2,3)
(1,2,3,4) -> [1;2;3;4]
Run Code Online (Sandbox Code Playgroud)
我需要两个函数来做到这一点:
let listToTuple list = ...
let tupleToList tuple = ...
Run Code Online (Sandbox Code Playgroud)
先感谢您.
Huu*_*som 19
除了listToTuple,那么pblasucci有正确的答案.但是你不会对结果感到满意,除非你对所涉及的类型类型有所了解,或者如果你不想进行大量的装箱和拆箱.
let tupleToList t =
if Microsoft.FSharp.Reflection.FSharpType.IsTuple(t.GetType())
then Some (Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields t |> Array.toList)
else None
let listToTuple l =
let l' = List.toArray l
let types = l' |> Array.map (fun o -> o.GetType())
let tupleType = Microsoft.FSharp.Reflection.FSharpType.MakeTupleType types
Microsoft.FSharp.Reflection.FSharpValue.MakeTuple (l' , tupleType)
Run Code Online (Sandbox Code Playgroud)
Tom*_*cek 14
正如已经指出的那样,这是一个棘手的问题,因为元组不是单一类型 - 它是一个类型的系列,如int * int * intor int * int和F#没有提供任何方式将整个类型的系列作为参数.您可以编写许多类似的函数(非常不舒服)或使用反射(这有点慢,并且不是类型安全的).
或者,您可以将函数限制为具有某种结构的元组 - 例如(1, 2, 3, 4),您可以使用嵌套元组,而不是使用它(1, (2, (3, 4))).这有点不太舒服,但它保持了类型安全,并没有那么糟糕.
然后,您可以轻松编写组合器,以便动态构建转换函数:
// creates function for converting tuple (possibly with a nested
// tuple in the second component to list
let tl f (a, b) = a::(f b)
// converts last element of the tuple to singleton list
let te a = [a]
Run Code Online (Sandbox Code Playgroud)
然后你可以组合函数tl并te创建一个类型安全的函数,将包含4个元素的嵌套元组转换为如下列表:
let l = (1, (2, (3, 4))) |> (tl (tl (tl te)))
Run Code Online (Sandbox Code Playgroud)
类似地,您可以创建将列表转换为元组的函数 - 请注意,如果列表与预期格式不匹配,这可能会引发异常:
let le = function
| [x] -> x
| _ -> failwith "incompatible"
let lt f = function
| [] -> failwith "incompatible"
| x::xs -> (x, f xs)
// convert list to a tuple of four elements
let t = [1; 2; 3; 4] |> lt (lt (lt le))
Run Code Online (Sandbox Code Playgroud)
我想这可能与类型安全和可重用函数一样,可以在元组和列表之间进行转换.这根本不是完美的,但这是因为你试图实现一个很少使用的操作.在F#中,元组和列表之间的区别比Python中更明显(Python是动态的,因此它不必处理静态类型安全性).