从可能性池中选择FsCheck生成器

Tho*_*eck 6 f# fscheck

有没有办法在FsCheck中生成一个字符串,只从每个字符串列表中选择一个项目然后连接结果?

我只是完全陷入困境,似乎无法弄明白.我查看了文档github repo中的类似内容.而且我已经从FSharpForFunAndProfit完成了对FsCheck的大部分阅读.

这就像我想的那样:

let rand = System.Random()
let randInt max = rand.Next(0, max)

let selectLetter (string: string) = 
    let whichLettersIndex = String.length string |> randInt
    string.Substring(whichLettersIndex, 1)

let generateOddlySpelledWord listOfStrings = 
    List.map selectLetter listOfStrings
    |> String.concat ""

let usingGenerateOddlySpelledWord =
    generateOddlySpelledWord ["zZ"; "oO0Ò"; "eEê"]
Run Code Online (Sandbox Code Playgroud)

这应该产生类似"Z0ê"或"zÒE"的东西.

Mar*_*ann 6

这样做你想要的吗?

open FsCheck

let createGenerators (l : string seq) =
    l |> Seq.map Gen.elements |> Seq.toList

type OddlySpelledWords =
    static member String() =
        ["zZ"; "oO0Ò"; "eEê"]
        |> createGenerators
        |> Gen.sequence
        |> Gen.map (List.map string >> String.concat "")
        |> Arb.fromGen
Run Code Online (Sandbox Code Playgroud)

特别测试:

open FsCheck.Xunit

[<Property(Arbitrary = [| typeof<OddlySpelledWords> |])>]
let test (s : string) =
    printfn "%s" s
Run Code Online (Sandbox Code Playgroud)

输出(截断):

  z0ê
  ZÒe
  ZOe
  zoê
  ZÒe
  zoê
  Z0e
  zoê
  z0ê
  ZOe
  zÒê
  z0E
  zoe
Run Code Online (Sandbox Code Playgroud)

说明

createGenerators函数具有类型seq string -> Gen<char> list,并且它Gen使用每个字符串创建一个Gen.elements,因为字符串也是一个char seq; Gen.elements创建一个将从每个字符串中Gen选择其中一个char值.

然后它用于Gen.sequence转换Gen<char> list为a Gen <char list>,然后从那里映射.


顺便说一下,你也可以内联createGenerators:

type OddlySpelledWords =
    static member String() =
        ["zZ"; "oO0Ò"; "eEê"]
        |> List.map Gen.elements
        |> Gen.sequence
        |> Gen.map (List.map string >> String.concat "")
        |> Arb.fromGen
Run Code Online (Sandbox Code Playgroud)

  • `List.reduce`的问题在于它很脆弱,所以我倾向于避免它.如果你不相信我,试试这个:`List.empty <string> |> List.reduce(+)`. (2认同)