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