与List类型匹配的FSharp模式

时间:2015-05-22 20:58:22

标签: list f# pattern-matching

我希望匹配" obj"类型的对象obj1。根据其实际类型。 问题是列表类型的类型检查模式(下例中的第二个)与F#列表不匹配。

let obj1 = [1;2;3] :> obj
match obj1 with
    | :? System.Array as a -> printfn "it's an array: %A" a
    | :? List<_> as l -> printfn "It's a list: %A" l
    | _ -> printfn "other type"

输出&#34;其他类型&#34;,虽然我希望它是&#34;它是一个列表:[1; 2; 3]&#34;

如何正确检查列表类型?

3 个答案:

答案 0 :(得分:3)

obj : [any type]

您需要做的是区分您的obj是否为泛型类型。通过.GetType()获取它的类型,你会找到合适的属性。

obj : [some type of the form T<'T1, 'T2, ..., 'Tn> for concrete types T1, T2, ..., Tn]

如果是,那么通过使用.GetType()

获得的类型的appropritate方法获得泛型类型定义
obj : [some type of the form T<'T1, 'T2, ..., 'Tn> with T1, T2, ..., Tn not bound yet]

此类型您现在可以与typedefof<_ list>进行比较(_ list被推断为obj list,但typedefoftypeof相对于let ty = obj.GetType() match obj with | unknownType when not ty.IsGenericType -> "some non-generic type, probably a concrete collection" | list when ty.GetGenericTypeDefinition() = typedefof<_ list> -> "list" | array when ty.GetGenericTypeDefinition() = typedefof<_ array> -> "array" | _ -> "something else, i.e. a generic type that we don't know" 你的通用类型定义)。

最终代码看起来像这样(伪代码)

apt-get install <service-name>

答案 1 :(得分:2)

Daniel Fabian已经在他的回答中解释了这个问题。

实现其解决方案的一种方法是使用Active Pattern

let (|IsList|_|) (candidate : obj) =
    let t = candidate.GetType()
    if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<list<_>>
    then Some (candidate :?> System.Collections.IEnumerable)
    else None

您现在可以更改匹配项以使用此活动模式:

let obj1 = [1;2;3] :> obj
match obj1 with
    | :? System.Array as a -> printfn "it's an array: %A" a
    | IsList l -> printfn "It's a list: %A" l
    | _ -> printfn "other type"

打印:

> It's a list: [1; 2; 3]

答案 2 :(得分:-2)

我不打电话给List&lt; _&gt;作为F#列表 - 它是.NET框架类型。您可以将它与(int list)类型匹配 - 它是F#list:

match obj1 with | :? (int list) as l -> 1 | _ -> 0
相关问题