首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >f#模式匹配序列:?seq<_> (IEnumerable)

f#模式匹配序列:?seq<_> (IEnumerable)
EN

Stack Overflow用户
提问于 2020-06-26 19:33:03
回答 2查看 147关注 0票数 1

我希望将结果发送到一个方法,该方法将内容输出到控制台/日志

我曾希望检测结果是否包含IEnumerable并遍历该集合以获取其结果。

这无法识别seq,只是简单地将其标识为Other Object

抱歉,我太罗嗦了。

代码语言:javascript
复制
let rec LogResultGeneric (logInfo: string -> unit, logError: string -> unit) (result: Result<_, _>) =
    let innerSelect (item: _) =
        match item |> box with
        | :? Result<_, _> as res ->
            "RESULT" |> logInfo
            res |> LogResultGeneric(logInfo, logError)
        | _ ->
            "VALUE" |> logInfo
            item |> LogValueGeneric logInfo

    "DISPLAY OUTCOME : " + result.ToString() |> logInfo 
    match result with
    | Error msg ->
        "ERROR RESULT" |> logError
        match msg |> box with
        | :? string as msg -> msg |> logError
        | _ -> msg.ToString() |> logError

    | Ok payload ->
        "OK RESULT" |> logInfo

        match payload |> box with
        | :? seq<obj> as s ->
            "IENUMERABLE" |> logInfo
            s
            |> Seq.iter innerSelect
        | _ ->
            "VALUE" |> logInfo
            payload |> LogValueGeneric logInfo
        |> ignore
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-26 19:56:27

将值与泛型类型进行模式匹配是很棘手的,因为编译器不会静态地知道seq<'a>中的'a应该是什么。针对seq<obj>的模式匹配也不起作用,因为例如seq<int>没有实现seq<obj>

但是,对于集合,您是幸运的,因为泛型IEnumerable<'T>继承自非泛型IEnumerable,因此您可以使用它:

代码语言:javascript
复制
let print payload = 
  match box payload with 
  | :? System.Collections.IEnumerable as ie ->
      let en = ie.GetEnumerator()
      while en.MoveNext() do
        printfn "ITEM: %A" en.Current
  | v -> 
      printfn "VALUE: %A" v

print [1;2;3]
print "ABC"

对于没有非泛型基类型的泛型类型,比如option<'T>,要让这样的东西工作起来比较困难,而且通常需要反射。

一个技巧是有一个通用的helper类,并使用反射将其指定为正确的类型,然后调用该方法(但通常,这非常难看):

代码语言:javascript
复制
type OptionPrinter<'T> = 
  static member Print(o:option<'T>) = 
    match o with 
    | None -> printfn "Nothing"
    | Some v -> printfn "Something: %A" v 

let print payload = 
  match box payload with 
  | :? System.Collections.IEnumerable as ie ->
      let en = ie.GetEnumerator()
      while en.MoveNext() do
        printfn "ITEM: %A" en.Current
  | null -> 
      printfn "NULL (or None)"
  | v when v.GetType().IsGenericType && 
          v.GetType().GetGenericTypeDefinition() = typedefof<option<_>> ->
      let tya = v.GetType().GetGenericArguments()
      let ty = typedefof<OptionPrinter<_>>.MakeGenericType(tya)
      ty.GetMethod("Print").Invoke(null, [| v |]) |> ignore
  | v -> 
      printfn "VALUE: %A" v

print [1;2;3]
print "ABC"
print (Some 10)
print None
票数 5
EN

Stack Overflow用户

发布于 2020-06-27 05:58:53

作为对Tomas's answer的扩展注释:只要您愿意使用反射,您就可以直接调用泛型方法,而不依赖泛型类型。通过这种方式,我们也可以处理Result<_,_>类型区分的联合。

代码语言:javascript
复制
type TypePrinter =
    static member PrintOption o =
        match o with
        | None -> printfn "Nothing"
        | Some x -> printfn "Something: %A" x
    static member PrintResult r =
        match r with
        | Error e-> printfn "Error: %A" e
        | Ok x -> printfn "Ok: %A" x

let invokeGenericMethod methodName o =
    typeof<TypePrinter>.GetMethod(methodName)
        .MakeGenericMethod(o.GetType().GetGenericArguments())
        .Invoke(null, [| o |]) |> ignore
let isOption o =
    o.GetType().IsGenericType &&
    o.GetType().GetGenericTypeDefinition() =
        typedefof<Option<_>>
let isResult o =
    o.GetType().IsGenericType &&
    o.GetType().BaseType.GetGenericTypeDefinition() =
        typedefof<Result<_,_>>

let print payload = 
    match box payload with 
    | :? System.Collections.IEnumerable as ie ->
        for x in ie do
            printfn "ITEM: %A" x
    | null -> 
        printfn "NULL (or None)"
    | v when isOption v ->
        invokeGenericMethod "PrintOption" v
    | v when isResult v ->
        invokeGenericMethod "PrintResult" v
    | v ->
        printfn "VALUE: %A" v

print [1..3]
print "ABC"
print (Some 10)
print None
print (Ok 42)
print (Error "Oh no")
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62593837

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档