F#:如何优雅地选择和分组受歧视的工会? [英] F#: how to elegantly select and group discriminated unions?
本文介绍了F#:如何优雅地选择和分组受歧视的工会?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
说我有一个形状列表:
type shape =
| Circle of float
| Rectangle of float * float
let a = [ Circle 5.0; Rectangle (4.0, 6.0)]
然后我该如何测试一个圆存在吗?我可以为每个形状创建一个函数
How can I then test e.g. a Circle exists in a? I could create a function for each shape
let isCircle s =
match s with
| Circle -> true
| _ -> false
List.exists isCircle a
但是我觉得F#中必须有一种更优雅的方式,除了必须为每种形状类型定义这样的功能.有吗?
but I feel there must be a more elegant way in F#, other than having to define such a function for each shape type. Is there?
相关的问题是如何根据形状类型对形状列表进行分组:
Related question is how to group a list of shapes, based on shape types:
a |> seq.groupBy( <shapetype? >)
推荐答案
您可以将F#反射与引号结合使用以获得通用解决方案
you can combine F# reflection with quotations to get generic solution
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
type Shape =
| Circle of float
| Rectangle of float * float
let isUnionCase (c : Expr<_ -> 'T>) =
match c with
| Lambda (_, NewUnionCase(uci, _)) ->
let tagReader = Microsoft.FSharp.Reflection.FSharpValue.PreComputeUnionTagReader(uci.DeclaringType)
fun (v : 'T) -> (tagReader v) = uci.Tag
| _ -> failwith "Invalid expression"
let a =
[ Circle 5.0; Rectangle (4.0, 6.0)]
|> List.filter (isUnionCase <@ Rectangle @>)
printf "%A" a
这篇关于F#:如何优雅地选择和分组受歧视的工会?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文