如何从 FsCheck.Gen.choose 中提取整数
How extract the int from a FsCheck.Gen.choose
我是 F# 的新手,看不到如何从中提取 int 值:
let autoInc = FsCheck.Gen.choose(1,999)
编译器说类型是 Gen<int>
,但无法从中获取 int!。我需要将它转换成十进制,这两种类型不兼容。
从消费者的角度来看,您可以使用 Gen.sample
组合器,给定生成器(例如 Gen.choose
),返回一些示例值。
Gen.sample
的签名是:
val sample : size:int -> n:int -> gn:Gen<'a> -> 'a list
(* `size` is the size of generated test data
`n` is the number of samples to be returned
`gn` is the generator (e.g. `Gen.choose` in this case) *)
您可以忽略 size
,因为 Gen.choose
会忽略它,因为它的分布是均匀的,并且可以执行以下操作:
let result = Gen.choose(1,999) |> Gen.sample 0 1 |> Seq.exactlyOne |> decimal
(* 0 is the `size` (gets ignored by Gen.choose)
1 is the number of samples to be returned *)
result
应该是闭区间[1, 999]中的一个值,例如897.
您好,补充一下 Nikos 已经告诉您的内容,这是您如何获得 1 到 999 之间的小数:
#r "FsCheck.dll"
open FsCheck
let decimalBetween1and999 : Gen<decimal> =
Arb.generate |> Gen.suchThat (fun d -> d >= 1.0m && d <= 999.0m)
let sample () =
decimalBetween1and999
|> Gen.sample 0 1
|> List.head
您现在只需使用 sample ()
即可取回随机小数。
如果您只想要 1 到 999 之间的整数,但已将其转换为 decimal
,您可以这样做:
let decimalIntBetween1and999 : Gen<decimal> =
Gen.choose (1,999)
|> Gen.map decimal
let sampleInt () =
decimalIntBetween1and999
|> Gen.sample 0 1
|> List.head
您可能真正想做的事情
我用它来为您编写一些不错的类型并像这样检查属性(这里使用 Xunit 作为测试框架和 FsCheck.Xunit 包:
open FsCheck
open FsCheck.Xunit
type DecTo999 = DecTo999 of decimal
type Generators =
static member DecTo999 =
{ new Arbitrary<DecTo999>() with
override __.Generator =
Arb.generate
|> Gen.suchThat (fun d -> d >= 1.0m && d <= 999.0m)
|> Gen.map DecTo999
}
[<Arbitrary(typeof<Generators>)>]
module Tests =
type Marker = class end
[<Property>]
let ``example property`` (DecTo999 d) =
d > 1.0m
Gen<'a>
是一种本质上抽象了一个函数 int -> 'a
的类型(实际类型有点复杂,但我们暂时忽略)。这个函数是纯函数,即当给定相同的 int 时,你每次都会得到相同的 'a back 实例。这个想法是 FsCheck 生成一堆随机整数,将它们提供给 Gen
函数,产生您感兴趣的 'a
类型的随机实例,并将它们提供给测试。
所以你无法真正取出 the int。你手中有一个函数,它给定一个 int,生成另一个 int。
Gen.sample
如另一个答案中所述,本质上只是将一系列随机整数提供给函数并将其应用于每个函数,返回结果。
这个函数是纯函数这一事实很重要,因为它保证了可重复性:如果 FsCheck 找到一个测试失败的值,您可以记录输入 Gen
函数的原始 int - 重新运行使用该种子进行测试可以保证生成相同的值,即重现错误。
我是 F# 的新手,看不到如何从中提取 int 值:
let autoInc = FsCheck.Gen.choose(1,999)
编译器说类型是 Gen<int>
,但无法从中获取 int!。我需要将它转换成十进制,这两种类型不兼容。
从消费者的角度来看,您可以使用 Gen.sample
组合器,给定生成器(例如 Gen.choose
),返回一些示例值。
Gen.sample
的签名是:
val sample : size:int -> n:int -> gn:Gen<'a> -> 'a list
(* `size` is the size of generated test data
`n` is the number of samples to be returned
`gn` is the generator (e.g. `Gen.choose` in this case) *)
您可以忽略 size
,因为 Gen.choose
会忽略它,因为它的分布是均匀的,并且可以执行以下操作:
let result = Gen.choose(1,999) |> Gen.sample 0 1 |> Seq.exactlyOne |> decimal
(* 0 is the `size` (gets ignored by Gen.choose)
1 is the number of samples to be returned *)
result
应该是闭区间[1, 999]中的一个值,例如897.
您好,补充一下 Nikos 已经告诉您的内容,这是您如何获得 1 到 999 之间的小数:
#r "FsCheck.dll"
open FsCheck
let decimalBetween1and999 : Gen<decimal> =
Arb.generate |> Gen.suchThat (fun d -> d >= 1.0m && d <= 999.0m)
let sample () =
decimalBetween1and999
|> Gen.sample 0 1
|> List.head
您现在只需使用 sample ()
即可取回随机小数。
如果您只想要 1 到 999 之间的整数,但已将其转换为 decimal
,您可以这样做:
let decimalIntBetween1and999 : Gen<decimal> =
Gen.choose (1,999)
|> Gen.map decimal
let sampleInt () =
decimalIntBetween1and999
|> Gen.sample 0 1
|> List.head
您可能真正想做的事情
我用它来为您编写一些不错的类型并像这样检查属性(这里使用 Xunit 作为测试框架和 FsCheck.Xunit 包:
open FsCheck
open FsCheck.Xunit
type DecTo999 = DecTo999 of decimal
type Generators =
static member DecTo999 =
{ new Arbitrary<DecTo999>() with
override __.Generator =
Arb.generate
|> Gen.suchThat (fun d -> d >= 1.0m && d <= 999.0m)
|> Gen.map DecTo999
}
[<Arbitrary(typeof<Generators>)>]
module Tests =
type Marker = class end
[<Property>]
let ``example property`` (DecTo999 d) =
d > 1.0m
Gen<'a>
是一种本质上抽象了一个函数 int -> 'a
的类型(实际类型有点复杂,但我们暂时忽略)。这个函数是纯函数,即当给定相同的 int 时,你每次都会得到相同的 'a back 实例。这个想法是 FsCheck 生成一堆随机整数,将它们提供给 Gen
函数,产生您感兴趣的 'a
类型的随机实例,并将它们提供给测试。
所以你无法真正取出 the int。你手中有一个函数,它给定一个 int,生成另一个 int。
Gen.sample
如另一个答案中所述,本质上只是将一系列随机整数提供给函数并将其应用于每个函数,返回结果。
这个函数是纯函数这一事实很重要,因为它保证了可重复性:如果 FsCheck 找到一个测试失败的值,您可以记录输入 Gen
函数的原始 int - 重新运行使用该种子进行测试可以保证生成相同的值,即重现错误。