Я хочу добавить другое решение, которое работает с цитатами для каждого случая объединения, на основе одного предоставленного деско. Вот оно:
open Microsoft.FSharp.Quotations.Patterns
open Microsoft.FSharp.Reflection
let rec isUnionCase = function
| Lambda (_, expr) | Let (_, _, expr) -> isUnionCase expr
| NewTuple exprs ->
let iucs = List.map isUnionCase exprs
fun value -> List.exists ((|>) value) iucs
| NewUnionCase (uci, _) ->
let utr = FSharpValue.PreComputeUnionTagReader uci.DeclaringType
box >> utr >> (=) uci.Tag
| _ -> failwith "Expression is no union case."
Определяемый таким образом, isUnionCase работает так, как показал desco, но даже в случаях объединения, которые пусты или имеют более одного значения. Вы также можете ввести кортеж объединенных делений через запятую. Учтите это:
type SomeType =
| SomeCase1
| SomeCase2 of int
| SomeCase3 of int * int
| SomeCase4 of int * int * int
| SomeCase5 of int * int * int * int
let list =
[
SomeCase1
SomeCase2 1
SomeCase3 (2, 3)
SomeCase4 (4, 5, 6)
SomeCase5 (7, 8, 9, 10)
]
list
|> List.filter (isUnionCase <@ SomeCase4 @>)
|> printfn "Matching SomeCase4: %A"
list
|> List.filter (isUnionCase <@ SomeCase3, SomeCase4 @>)
|> printfn "Matching SomeCase3 & SomeCase4: %A"
Первый предоставленный мною isUnionCase работал только для единичных проверок. Позже я добавил проверку выражения для NewTuple и подумал, что вам это может понравиться. Просто убедитесь, что если вы измените код, предварительные вычисления все еще работают, вот почему iucs
определено вне возвращенной анонимной функции.