【问题标题】:F# Pattern Matching on Generic Parameter通用参数上的 F# 模式匹配
【发布时间】:2018-10-10 20:15:02
【问题描述】:

我这里有一个奇怪的。我想匹配泛型参数的类型。这是我目前所拥有的:

open System.Reflection

type Chicken = {
    Size : decimal
    Name : string
}

let silly<'T> x =
    match type<'T> with
    | typeof<Chicken> -> printfn "%A" x
    | _ -> printfn "Didn't match type"
    enter code here

我希望silly&lt;'T&gt; 函数采用通用参数,然后匹配函数中的类型以确定输出。现在我收到一个关于不正确缩进的编译器错误。我很确定缩进很好,但是我正在做的事情编译器根本不喜欢。想法?我有一个蛮力解决方法,但这种方法会简单得多。

【问题讨论】:

  • 为什么需要匹配System.Type 而不是match box arg with :? Chicken ...?拳击是必要的,但您仍然可以将arg 限制为'T
  • @kaefer 装箱如果已知参数是引用类型也是免费的。

标签: generics f# pattern-matching


【解决方案1】:

我想这就是你要找的:

let silly x =
    match box x with 
    | :? Chicken as chicken -> printfn "is a  chicken = %s %A" chicken.Name chicken.Size
    | :? string  as txt     -> printfn "is a  string  = '%s'"  txt
    | :? int     as n       -> printfn "is an int     = %d"    n
    | _                     -> printfn "Didn't match type"

这样称呼它:

silly "Hello"
silly 7
silly { Name = "Claudius" ; Size = 10m }

// is a  string  = 'Hello'
// is an int     = 7
// is a  chicken = Claudius 10M

【讨论】:

  • 这似乎比公认的答案更直接。
  • 为什么这需要拳击?好奇
  • 类型测试运算符:? 适用于子类型。由于x 是通用的,编译器无法确定其子类型。 boxx 转换为obj(相当于使用x :&gt; obj),一切都是obj 的子类型。否则您会收到错误消息:type test from type 'a to Chicken involves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed.
【解决方案2】:

这是我一直在做的事情,不确定它是否是“最好的”,但它对我和我的团队有效且有意义。

let silly<'T> x =
  match typeof<'T> with
  | t when t = typeof<TypeA>  -> TypeASpecificFunction x
  | t when t = typeof<TypeB>  -> TypeBSpecificFunction x
  | t when t = typeof<TypeC>  -> TypeCSpecificFunction x
  | _                         -> printfn "Didn't match type"

它需要你有一个通用函数,这种方法不能直接在 typeof 上工作,你必须做 typeof。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-22
    • 1970-01-01
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多