2

我是 F# 的新手,看不到如何从以下位置提取 int 值:

let autoInc = FsCheck.Gen.choose(1,999)

编译器说类型是Gen<int>,但无法从中获取 int !我需要将其转换为十进制,两种类型都不兼容。

4

3 回答 3

3

从消费者的角度来看,您可以使用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

于 2015-04-17T04:43:25.663 回答
2

嗨,补充一下 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
于 2015-04-17T04:52:43.137 回答
1

Gen<'a>是一种本质上抽象函数int -> 'a的类型(实际类型要复杂一些,但我们现在先忽略)。这个函数是纯函数,即当给定相同的 int 时,每次都会得到相同的 'a 实例。这个想法是 FsCheck 生成一堆随机整数,将它们提供给函数,输出您感兴趣Gen的类型的随机实例,并将它们提供给测试。'a

所以你不能真正摆脱int。你手中有一个函数,给定一个 int,生成另一个 int。

Gen.sample如另一个答案中所述,本质上只是将一系列随机整数提供给函数并将其应用于每个整数,然后返回结果。

这个函数是纯的这一事实很重要,因为它保证了可重复性:如果 FsCheck 找到一个测试失败的值,您可以记录输入Gen函数的原始 int - 使用该种子重新运行测试可以保证生成相同的值值,即重现错误。

于 2015-04-17T08:13:53.923 回答