我想以一种特定的方式格式化一个元组,我试图通过检查该元组的类型(2个元素,3个元素等)来做到这一点。我在第三行收到一条错误消息:
This runtime coercion of type test from type
'd
to
'a * ('b * 'c)
involves an indeterminate type based on the information prior to this program point.
Runtime type tests are not allowed on some type. Further type annotations are needed.
这是我的尝试:
let namer x =
match x with
| :? ('a * ('b * 'c)) as a, b, c -> sprintf "%s_%s_%s" (a.ToString()) (b.ToString()) (c.ToString())
| :? ('a * 'b) as a, b -> sprintf "%s_%s" (a.ToString()) (b.ToString())
| a -> sprintf "%s" (a.ToString())
您应该如何做这样的事情?我希望能够根据元组的类型来格式化字符串。
我最终想要的是能够将嵌套的元组“展平”为字符串,而无需加上括号。例如:
// What I want
let x = (1, (2, (3, 4)))
let name = namer x
printfn "%s" name
> 1_2_3_4
更新:这与“如何在F#列表和F#元组之间转换?”问题不同。找到here。我知道该怎么做。我想要的是能够检测我是否有一个元组以及什么类型的元组。理想的情况是可以使用单个元素,元组或嵌套2个元素元组的通用函数。例如,法律依据为:
let name = namer 1
// or
let name = namer (1, 2)
// or
let name = namer (1, (2, 3))
// or
let name = namer (1, (2, (3, 4)))
我也想处理非整数值。例如:
let name = namer (1, ("2", (3, "chicken")))
答案 0 :(得分:2)
您可以通过一些反射和递归函数来实现:
let isTuple tuple =
tuple.GetType() |> Reflection.FSharpType.IsTuple
let getFields (tuple: obj) =
tuple |> Reflection.FSharpValue.GetTupleFields |> Array.toList
let rec flatten fields =
fields
|> List.collect(
fun tuple ->
if isTuple tuple
then flatten (getFields tuple)
else [tuple]
)
let namer(tuple: obj) =
if isTuple tuple
then tuple |> getFields |> flatten
else [tuple]
namer(1, "test") |> printfn "%A"
namer(1, ("2", (3, "chicken"))) |> printfn "%A"
灵感来自: