能否从F#泛化Set定义中移除操作字典?
移除ComparisonOps操作字典的方案
当然可以移除这个操作字典啦!你的MySet<'t>已经带有when 't : comparison的约束,这意味着F#标准库会为所有满足该约束的类型自动提供完整的比较支持——就是我们日常用的>、>=、=、<=、<这些运算符,完全不需要手动维护一个操作字典来封装它们。
修改后的类型定义
首先我们可以保留Comparison类型(用来表示不等式规则),然后直接简化MySet的定义,去掉冗余的ComparisonOps:
type Comparison = | GE | GT | LE | LT | EQ type MySet<'t when 't : comparison> = | List of list<'t> // 基于具体列表的集合 | Sequence of seq<'t> // 基于序列的集合 | ComparisonRule of Comparison * 't // 用不等式规则定义的集合(比如"所有大于5的元素")
实现比较逻辑的辅助函数
接下来只需要一个简单的辅助函数,把Comparison枚举映射到对应的标准比较运算符即可:
let getComparisonFilter (comp: Comparison) (threshold: 't) : 't -> bool = match comp with | GT -> fun x -> x > threshold | GE -> fun x -> x >= threshold | LT -> fun x -> x < threshold | LE -> fun x -> x <= threshold | EQ -> fun x -> x = threshold
实际使用示例
比如我们可以用这个规则来定义集合,再结合具体元素源进行过滤:
// 定义"所有小于10的整数"这个集合规则 let lessThanTen = ComparisonRule(LT, 10) // 写一个函数来解析MySet并获取符合条件的元素序列 let resolveMySet (source: seq<'t>) (mySet: MySet<'t>) : seq<'t> = match mySet with | List lst -> lst |> Seq.ofList | Sequence seq -> seq | ComparisonRule(comp, threshold) -> source |> Seq.filter (getComparisonFilter comp threshold) // 测试:从0到20的整数中筛选出小于10的元素 resolveMySet [0..20] lessThanTen // 输出:seq [0; 1; 2; ...; 9]
为什么这个方案更优
- 减少冗余:不需要手动维护
ComparisonOps的每个字段,避免了漏写、错写比较逻辑的风险 - 利用F#原生支持:
comparison约束确保了所有合法类型都能直接使用标准比较运算符,包括自定义类型(只要给类型加上[<Comparison>]属性即可) - 逻辑更清晰:直接用枚举和辅助函数映射比较规则,代码可读性更高
内容的提问来源于stack exchange,提问作者Soldalma
相关产品推荐
相关产品推荐

