F#模式匹配:匹配功能/子类型列表吗? [英] F# Pattern Matching: Matching functions/lists of subtypes?

查看:98
本文介绍了F#模式匹配:匹配功能/子类型列表吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

let f (O: obj) = 
    match O with
        | :? (obj -> list<obj>) -> "win"
        | :? list<obj> -> "list!"
        | _ -> "fail"

Console.WriteLine(f(fun x -> ["lol"]))
Console.WriteLine(f(["lol"]))

我认为应该

打印两次"fail",因为我给了我一个obj -> list<String>函数,而不是obj -> list<obj>.有什么办法可以使它们匹配吗?在使用匿名功能之前,我可以将每个列表上载到list<obj>中,也可以将所有内容上载到obj中,然后再将其放入列表中.

prints "fail" twice, as I suppose it should, because I am giving i a function obj -> list<String>, which is not a obj -> list<obj>. Is there any way to make them match though? I could upcast each list into a list<obj> before making an anonymous function out of it, or I could upcast everything to obj before putting it into the list.

这些工作中的任何一项都可以使之匹配,但是我认为这是协方差/协方差本来应该解决的问题?如果我弄错了请纠正我

Either of those works and makes it match, but i thought this was the problem that covariance/contravariance was meant to have already solved? Correct me if i'm mistaken

推荐答案

不幸的是,您无法使用任何内置模式匹配来解决此问题.

Unfortunately, you can't solve this using any built-in pattern matching.

找出obj值是否为某些F#函数的唯一方法是使用F#反射并在该类型上调用FSharpType.IsFunction方法.您可以在示例中检查情况,如下所示:

The only way to find out whether an obj value is some F# function is to use F# Reflection and call the FSharpType.IsFunction method on the type. You can check for the case in your example like this:

open System    
open Microsoft.FSharp.Reflection    

let f (o : obj) =  
  let ty = o.GetType() 
  if FSharpType.IsFunction(ty) then
    let tyFrom, tyTo = FSharpType.GetFunctionElements(ty)
    if tyTo.IsGenericType && tyTo.GetGenericTypeDefinition() = typedefof<list<_>> then
      printfn "win"
    else 
      printfn "wrong function"
  else
    printfn "not a function"

Console.WriteLine(f(fun x -> "lol"))    // wrong function
Console.WriteLine(f(fun x -> ["lol"]))  // win
Console.WriteLine(f(["lol"]))           // not a function

您可以将行为封装在F#活动模式中,以使语法更好(并在类型上使用模式匹配).但是,另一个问题是,这不能为您提供一个可用于实际动态调用该函数的函数.我认为没有内置的库函数,因此您可能需要使用.NET反射来动态调用Invoke方法.

You could encapsulate the behavior in an F# active pattern to make the syntax a bit nicer (and use pattern matching on types). However, another problem is that this doesn't give you a function that you could use to actually invoke the function dynamically. I don't think there is a built-in library function for this, so you'll probably need to use .NET reflection to call the Invoke method dynamically.

编辑:关于SO也有类似的相关问题.普遍的问题是您要匹配特定泛型类型的某些(任何)实例,因此列表等也会出现相同的问题.例如:

EDIT: There has been similar related questions on SO. The general problem is that you're matching against some (any) instantiation of a specific generic type, so the same issue arises with lists etc. See for example:

  • F# and pattern matching on generics...
  • Pattern matching against generic type...
  • How to cast an object to a list...

这篇关于F#模式匹配:匹配功能/子类型列表吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆