Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 使用';灵活';类型参数 将值与 | :? 列表为l->l//是否可以匹配从某个类型派生的类型的任何列表? |->failwith“不匹配”_F#_Pattern Matching - Fatal编程技术网

F# 使用';灵活';类型参数 将值与 | :? 列表为l->l//是否可以匹配从某个类型派生的类型的任何列表? |->failwith“不匹配”

F# 使用';灵活';类型参数 将值与 | :? 列表为l->l//是否可以匹配从某个类型派生的类型的任何列表? |->failwith“不匹配”,f#,pattern-matching,F#,Pattern Matching,不,很遗憾,这样做是不可能的-CLR没有提供任何有效的方式来进行这种类型的测试。请参阅和,了解一些(相当难看的)解决方案。如前所述,无法直接执行此操作(模式匹配只能绑定值,但不能绑定新类型变量)。除了kvb的(更通用的)解决方案外,您还可以使用以下事实:所有集合都实现非通用的IEnumerable,因此您可以检查此类型: match value with | :? list<#SomeType> as l -> l //Is it possible to match any l

不,很遗憾,这样做是不可能的-CLR没有提供任何有效的方式来进行这种类型的测试。请参阅和,了解一些(相当难看的)解决方案。

如前所述,无法直接执行此操作(模式匹配只能绑定值,但不能绑定新类型变量)。除了kvb的(更通用的)解决方案外,您还可以使用以下事实:所有集合都实现非通用的
IEnumerable
,因此您可以检查此类型:

match value with
| :? list<#SomeType> as l -> l //Is it possible to match any list of a type derived from SomeType?
| _ -> failwith "doesn't match"
将框值与
| :? System.Collections.IEnumerable为l时
//假定“l”的实际类型为“列表”或其他类型
//使用单个泛型类型参数(这不是完全正确的,因为
//它也可以是其他类型,但我们现在可以忽略它)
类型defof.IsAssignableFrom
(value.GetType().GetGenericArguments()[0])->
l |>顺序铸件
|->failwith“不匹配”

代码测试该值是否为非泛型
IEnumerable
,以及类型参数是否为
SomeType
的子类型。在这种情况下,我们得到了某个派生类型的列表,因此我们可以将其强制转换为一系列
SomeType
值(这与使用派生类型的值列表略有不同,但实际上并不重要)。

我后来需要类似的东西来匹配延迟实例。这是我的解决方案,以防有人觉得有用

match box value with 
| :? System.Collections.IEnumerable as l when 
     // assumes that the actual type of 'l' is 'List<T>' or some other type
     // with single generic type parameter (this is not fully correct, because
     // it could be other type too, but we can ignore this for now)
     typedefof<SomeType>.IsAssignableFrom
       (value.GetType().GetGenericArguments().[0]) -> 
   l |> Seq.cast<SomeType>
| _ -> failwith "doesn't match"
let(| Lazy | | |)(值:obj)=
如果框值为空,则
设typ=value.GetType()
如果typ.IsGenericType&&typ.GetGenericTypeDefinition()=typedefof,则
某些(typ.GetGenericArguments()[0])
没有别的
没有别的
用法:

let (|Lazy|_|) (value : obj) =
    if box value <> null then
        let typ = value.GetType()
        if typ.IsGenericType && typ.GetGenericTypeDefinition() = typedefof<Lazy<_>> then
            Some(typ.GetGenericArguments().[0])
        else None
    else None
将值与
|当typeof.IsAssignableFrom(typ)->(值:?>Lazy).value
|->failwith“不是懒惰的实例”

< /代码>

根据Par。14.5.2(解决子类型约束),它将不起作用,因为:“F#泛型类型不支持协方差或逆变。”

不是最干净的,但有效:

match value with
| Lazy typ when typeof<SomeType>.IsAssignableFrom(typ) -> (value :?> Lazy<_>).Value
| _ -> failwith "not an instance of Lazy<#SomeType>"
let matchType()
将框o与
| :? 类型1->printfn“类型1”
| :? 类型2->printfn“类型2”
|带有“未知类型”的故障
具有
|ex->failwith“%s”(例如ToString())

我认为这并不重要,但为什么需要与某种类型的列表匹配?如果列表是同质的,那么您可以简单地逐个元素处理列表元素,这很好。如果列表是异质的,那么无论如何你也不能把列表看作是一个逻辑单元。你想解决的问题是什么?我想我应该使用我的实际代码。我只是为了简单而使用列表。问题是如何对类型参数进行灵活匹配。
let matchType<'T> () =
    try
        let o = Activator.CreateInstance<'T> ()
        match box o with
        | :? Type1 -> printfn "Type1"
        | :? Type2 -> printfn "Type2"
        | _ -> failwith "unknown type"
    with
    | ex -> failwith "%s" (ex.ToString())