【问题标题】:FSharp check if tuple type or notFSharp 检查元组类型与否
【发布时间】:2021-06-08 20:20:57
【问题描述】:

我想以特定方式格式化元组,我试图通过检查元组的类型(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")))

【问题讨论】:

  • 为什么要建模为嵌套元组?这在 F# 中并不常见
  • @7sharp9 同意这并不常见。在这种情况下,我有一个计算表达式,其中我嵌套了 for...in...do 循环,我想在其中跟踪迭代器值并在最后调用 Run 时将其用作 id。我会有一篇博文,稍后我会详细说明。

标签: f#


【解决方案1】:

您可以通过一些反射和协同递归函数来实现这一点:

let isTuple tuple =
    tuple.GetType() |> Reflection.FSharpType.IsTuple 

let getFields (tuple: obj) = 
    tuple |> Reflection.FSharpValue.GetTupleFields |> Array.toList

let rec flatten fields =
    List.collect namer fields

and namer (tuple: obj) = 
    if isTuple tuple
    then tuple |> getFields |> flatten
    else [tuple]

namer(1, "test") |> printfn "%A"
namer(1, ("2", (3, "chicken"))) |> printfn "%A"

Try it online!

灵感来源:

【讨论】:

  • 这是否处理单例值的情况?例如,如果它只是 : 1 或“test”的值
  • 这太棒了!我能够将检查添加到namer 以处理单例值的情况。谢谢!这非常有帮助。
猜你喜欢
  • 1970-01-01
  • 2016-04-11
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多