Я новичок в F# и не понимаю, как извлечь значение int из:
let autoInc = FsCheck.Gen.choose(1,999)
Компилятор говорит, что это тип Gen<int>
, но не может получить из него 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.
Привет, чтобы добавить к тому, что уже сказал вам Никос, вот как вы можете получить десятичную дробь от 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
Operators.decimal<^T>
, например. .. |> Gen.sample 0 1 |> Seq.exactlyOne |> decimal
- person Nikos Baxevanis; 17.04.2015
Gen<'a>
— это тип, который по существу абстрагирует функцию int -> 'a
(фактический тип немного сложнее, но давайте пока его проигнорируем). Эта функция чистая, т. е. при задании одного и того же int вы каждый раз будете получать один и тот же экземпляр «a». Идея состоит в том, что FsCheck генерирует набор случайных целых чисел, передает их функции Gen
, получает случайные экземпляры интересующего вас типа 'a
и передает их тесту.
Таким образом, вы не можете получить the int. У вас есть функция, которая по заданному int генерирует другой int.
Gen.sample
, как описано в другом ответе, по сути, просто передает последовательность случайных целых чисел в функцию и применяет ее к каждому, возвращая результаты.
Тот факт, что эта функция является чистой, важен, потому что это гарантирует воспроизводимость: если FsCheck находит значение, для которого тест не пройден, вы можете записать исходное целое число, которое было передано в функцию Gen
— повторный запуск теста с этим начальным значением гарантированно сгенерирует одинаковые значения, т.е. воспроизвести ошибку.
Gen
? - person ildjarn   schedule 17.04.2015System.Random
. - person Fyodor Soikin   schedule 17.04.2015Gen.choose
, но я не дал вам ссылку на исходный код по какой-то причине - я дал вам ссылку на документацию, которую вы должны прочитать. - person ildjarn   schedule 17.04.2015