我有一个代表原始类型的判定联盟:
type Expr =
| Int of bigint
| Real of float
| Symbol of string
| Bool of bool
| List of Expr list
我正在编写一个函数list : obj list -> Expr list
,它会检查对象的类型并相应地将它们转换为Expr
:
let rec list : (obj list -> Expr list) = function
| head::tail ->
match head with
| :? string as x'-> Symbol (x') :: list tail
| :? int as x'-> Int(bigint x') :: list tail
| :? bigint as x' -> Int x' :: list tail
| :? bool as x' -> Bool x' :: list tail
| :? float as x' -> Real x' :: list tail
| :? Expr as x' -> x' :: list tail
| :? list<obj> as x' -> List(list x') :: list tail
| _ -> []
在嵌套列表上调用此函数时,| :? list<obj> as x' -> List(list x') :: list tail
似乎不匹配:list [1;[2;1]]
这完全编译但返回错误,表示匹配情况不完整,它看起来它正试图用list<int>
来处理这些情况并且找不到它。我希望list<obj>
匹配任何类型'a
的列表,但事实并非如此。 我应该编写哪种模式才能使其与任何类型的列表匹配?该函数适用于非嵌套对象列表。
答案 0 :(得分:4)
您无法使用模式匹配来检查对象是否为具有未指定泛型参数的泛型类型的值。您可以检查它是list<int>
还是list<obj>
,但它必须是此类型 - 因此当您使用{{1}检查类型时,list<int>
将不会匹配(另外,您可以编写:? list<obj>
,但编译器只会用:? list<_>
填充_
如果您只关心集合,则可以使用所有集合(列表,数组等)实现的非通用obj
接口:
System.Collections.IEnumerable
答案 1 :(得分:2)
模式匹配不完整,因为head
属于obj
类型。未涵盖的案例包括null
,obj ()
,1L
(64位整数),System.Version ()
,System.Guid("DAB51019-DF69-4547-BC3B-5CE06BE22A7B")
,[| 1; 2 |]
等
无法处理无数个案例,因为obj
表示任何,包括自定义类型。
我应该写什么模式才能让它与任何类型的列表匹配?
您始终可以使用通配符模式_
,但只有您知道在这种情况下会发生什么。