You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在gen计算表达式中实现Gen.filter的等效功能?

在FsCheck的gen计算表达式内实现过滤逻辑

原代码示例:

type Status = Pending | Activated | Deactivated
type Item = { Id: int; Status: Status }

let nonPendingItemGen =
    Arb.generate<Item>
    |> Gen.filter (fun item -> item.Id > 0 && item.Status <> Pending)

问题

能否将这段代码重构为在gen计算表达式内部实现过滤逻辑?

  • 尝试使用if语句时因分支类型不匹配失败;
  • 已找到通过生成序列再过滤的方案,但不够优雅。

解决方案

可以直接在gen计算表达式内通过递归重试的方式实现过滤,写法如下:

type Status = Pending | Activated | Deactivated
type Item = { Id: int; Status: Status }

let nonPendingItemGen = gen {
    let! item = Arb.generate<Item>
    if item.Id > 0 && item.Status <> Pending then
        return item
    else
        return! nonPendingItemGen // 不符合条件就递归重试当前生成器
}

这种写法和Gen.filter的底层逻辑一致,都是通过重试来筛选符合条件的生成值。需要注意的是,如果过滤条件过于严苛,可能会导致FsCheck生成值超时或失败,这是过滤类生成器的共性限制。

相比生成序列再过滤的方案,这种递归重试的写法更直观,完全在gen计算表达式内部完成逻辑,无需额外的序列操作。

内容的提问来源于stack exchange,提问作者Romain Deneau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:57:25