Рассмотрим дискриминируемый союз:
type DU = | Foo of string | Bar of int | Baz of decimal * float | Qux of bool
Я хотел бы создать список значений DU
с помощью FsCheck, но я не хочу, чтобы ни одно из значений не относилось к случаю Qux
.
Этот предикат уже существует:
let isQux = function Qux _ -> true | _ -> false
Первая попытка
Моя первая попытка создать список значений DU
без регистра Qux
была примерно такой:
type DoesNotWork =
static member DU () = Arb.from<DU> |> Arb.filter (not << isQux)
[<Property(MaxTest = 10 , Arbitrary = [| typeof<DoesNotWork> |])>]
let repro (dus : DU list) =
printfn "%-5b : %O" (dus |> List.exists isQux |> not) dus
Выполнение этого, похоже, приводит к переполнению стека, поэтому я предполагаю, что за сценой происходит то, что Arb.from<DU>
вызывает DoesNotWork.DU
.
Вторая попытка
Затем я попробовал это:
type DoesNotWorkEither =
static member DU () =
Arb.generate<DU>
|> Gen.suchThat (not << isQux)
|> Arb.fromGen
[<Property(MaxTest = 10 , Arbitrary = [| typeof<DoesNotWorkEither> |])>]
let repro (dus : DU list) =
printfn "%-5b : %O" (dus |> List.exists isQux |> not) dus
Та же проблема, что и выше.
Подробное решение
Это лучшее решение, которое я смог придумать до сих пор:
type WithoutQux =
static member DU () =
[
Arb.generate<string> |> Gen.map Foo
Arb.generate<int> |> Gen.map Bar
Arb.generate<decimal * float> |> Gen.map Baz
]
|> Gen.oneof
|> Arb.fromGen
[<Property(MaxTest = 10 , Arbitrary = [| typeof<WithoutQux> |])>]
let repro (dus : DU list) =
printfn "%-5b : %O" (dus |> List.exists isQux |> not) dus
Это работает, но имеет следующие недостатки:
- Кажется, много работы
- Он не использует уже доступную функцию
isQux
, поэтому кажется, что он слегка нарушает DRY. - На самом деле он не фильтрует, а только создает нужные случаи (поэтому фильтрует только путем пропуска).
- Это не особенно удобно в сопровождении, потому что, если я когда-нибудь добавлю пятый случай к
DU
, мне придется запомнить, чтобы также добавитьGen
для этого случая.
Есть ли более элегантный способ указать FsCheck отфильтровать значения Qux
?