fscheck генерирует строку с размером между min и max

Я пытаюсь написать генератор FsCheck, который генерирует строки с длиной в заданном интервале.

Моя попытка заключается в следующем:

let genString minLength maxLength = 
    let isValidLength (s : string) = 
        s.Length >= minLength && s.Length <= maxLength

    Arb.generate
    |> Gen.suchThat isValidLength
    |> Arb.fromGen

... и я получаю сообщение об ошибке:

"System.Exception : No instances of class FsCheck.Arbitrary`1[a] for type System.String with arguments set []"

Что я делаю не так?

Спасибо!

ОБНОВЛЕНИЕ 1:

Мне удалось написать генератор так:

let genStrings minLength maxLength = 
    gen {
        let! length = Gen.choose (minLength, maxLength)
        let! chars = Gen.arrayOfLength length Arb.generate<char>
        return new String(chars)
    }

Есть ли способ лучше?

ОБНОВЛЕНИЕ 2: я хотел добавить это как отдельный вопрос, но это почти та же проблема, что и моя первоначальная.

Поэтому я преобразовал приведенный выше код в следующую структуру, чтобы повторно использовать генератор последовательности:

let seqOfLength lengthInterval generator =
    gen {
        let! length = Gen.choose lengthInterval
        let! items = Gen.arrayOfLength length generator
        return items |> Seq.ofArray
    }

let sizedString lengthInterval =
    seqOfLength lengthInterval Arb.generate<char>
    |> Gen.map Strings.ofCharSeq

Теперь я получаю ошибку времени выполнения:

System.Exception : No instances of class FsCheck.Arbitrary`1[a] for type System.Char with arguments set []

... что возвращает меня к моей первоначальной проблеме: почему он не может найти ни одного экземпляра Arbitrary для System.Char? Я думал произвольные для базовых типов прописаны по умолчанию. Что я делаю не так?

Спасибо!


person vidi    schedule 08.10.2014    source источник
comment
Перейдите к вашему последнему примеру, который на сегодняшний день является наиболее производительным (остальные будут пробовать строки, пока не получат один с длиной в вашем интервале)   -  person Random Dev    schedule 08.10.2014
comment
Спасибо. Я оставлю вопрос открытым на некоторое время, может быть, кто-нибудь опубликует лучшее решение. Мне это кажется слишком сложным для такой распространенной задачи, как генерация строк.   -  person vidi    schedule 08.10.2014
comment
Прошло некоторое время с тех пор, как я в последний раз подробно смотрел, и, возможно, теперь есть помощник, но не так часто генерируются только строки в определенном диапазоне длины - обычно я бы использовал для этого условные свойства: fsharp.github.io/FsCheck/Properties.html - но, как я уже сказал, объявление генератора с использованием монады, как вы сделали, более производительный   -  person Random Dev    schedule 08.10.2014
comment
Я попробовал подход со свойствами, но получил исключение из-за исчерпания аргументов. Думаю, я оставлю код таким. Спасибо за комментарии!   -  person vidi    schedule 08.10.2014
comment
в этом случае это почти нормально, так как большинство проверенных значений будут лежать за пределами вашего диапазона - это ваш последний подход намного лучше   -  person Random Dev    schedule 08.10.2014
comment
моделированные классы типов немного особенные... просто оберните их обратно в gen { ... } - для работы Arbitrary.generate должны быть установлены значения по умолчанию (насколько я помню - прошло больше года, Я рассмотрел это) здесь вы используете его в контексте вашего модуля, и я подозреваю, что в это время произвольные значения еще не установлены - если вы завернете его в gen, рабочий процесс не будет запускаться только там, а внутри FsChecks .Check методы произвольные обязательно будет установлен - это немного похоже на утверждение исключений - вам нужно сделать вещи ленивыми, чтобы они происходили в нужное время   -  person Random Dev    schedule 10.10.2014
comment
Я был в отпуске, и теперь, когда я вернулся, мы до сих пор не починили генераторы, но у нас другая проблема. Я вернусь, если моя первоначальная проблема снова появится. Спасибо!   -  person vidi    schedule 26.10.2014
comment
В версии 1.0.2 я немного ускорил регистрацию генераторов по умолчанию. Можете ли вы проверить, исправляет ли это исключения, которые вы получаете?   -  person Kurt Schelfthout    schedule 28.10.2014


Ответы (1)


Ваш пример кода работает с FsCheck v2.14.3

let seqOfLength lengthInterval generator =
    gen {
        let! length = Gen.choose lengthInterval
        let! items = Gen.arrayOfLength length generator
        return items |> Seq.ofArray
    }
let stringOfLength lengthInterval =
    seqOfLength lengthInterval Arb.generate<char>
    |> Gen.map String.Concat
person DharmaTurtle    schedule 10.07.2020