Пользовательский генератор списков FsCheck, удовлетворяющий предикату - PullRequest
1 голос
/ 22 марта 2019

Для данного предиката pred : 'a list -> bool и генератора gen : Gen<'a> рассмотрим следующий генератор правильно сформированных списков, которые удовлетворяют предикату:

let wellFormedList pred gen =
   Gen.ofList gen
   |> Gen.filter pred 

Как упомянуто в руководстве FsCheck , должна быть высокая вероятность того, что предикат верен для случайного списка. К сожалению, это предположение не выполняется в моем случае. Таким образом, мне нужно определить собственный генератор для списков, которые удовлетворяют предикату.

Как определить собственный генератор, который запускается из пустого списка и дополняет его новыми случайными элементами, пока список не удовлетворяет предикату?

Возможно, мне нужно использовать вычислительное выражение gen { } для генераторов, но я не понимаю, как.

PS: я знаю, что, в отличие от первоначальной реализации wellFormedList, распределение такого пользовательского генератора не является равномерным по всем спискам, которые удовлетворяют предикату.

1 Ответ

1 голос
/ 22 марта 2019

Ну, если я правильно понимаю, я думаю, что это должно сделать это:

let wellFormedList (predicate:'a list -> bool) (myGen:Gen<'a>) = 
  gen {
    let! initialList = Gen.listOf myGen
    let mutable myList = initialList
    while not <| predicate myList do
      let! newVal = myGen
      myList <- (newVal :: myList)

    return myList      
  }

или, если вы хотели рекурсивную функцию:

let wellFormedList (predicate:'a list -> bool) (myGen:Gen<'a>) = 
  gen {
    let rec addIfNecessary listSoFar =
      if predicate listSoFar 
      then gen { return listSoFar }
      else gen { 
        let! newVal = myGen
        return! addIfNecessary (newVal :: listSoFar)
      }

    let! initialList = Gen.listOf myGen
    return! addIfNecessary initialList
  }

Я не проверялкакие дистрибутивы это вам дает.И, конечно, вы рискуете бесконечный цикл (или переполнение стека), если список никогда не сходится в форме, которая передает предикат.

...