[erlang-questions] Cannot make PropEr bitstring(B, U) generator to work

Motiejus Jakštys desired.mta@REDACTED
Tue Sep 11 17:36:58 CEST 2012

On Tue, Sep 11, 2012 at 4:40 PM, Manolis Papadakis <manopapad@REDACTED> wrote:
> PropEr first tries to resolve the expression "bitstring(8, 1)" to a
> generator, but that fails, because bitstring/2 is not a predefined
> generator, and there's no custom generator with that signature declared
> inside the module.

But... According to the Book of Wisdom[1], bitstring(B, U) is there.
And binary(S) is not. I haven't seen it before.

> PropEr then tries to find a type with that name, but that fails as well:
> bitstring/2 is not a predifined type (the way to express the same thing in
> the type language is <<_:8,_:_*1>>), and there's no local type with that
> signature.

Eh.. That would kinda do, but it raises a syntax error when used in
?FORALL context.

> Quick fix: If you're OK with using only unit values of either 8 or 1, then
> you can use the predefined generator binary(Base) or bitstring(Base)
> respectively. If you need other unit values, you'll have to write a custom
> generator.

Actually, I want binaries with length 0..1MiB-1:

        ?LET(Len, integer(0, 1 bsl 20 - 1), Len),
        {binary(Len), Len}

So for this, binary(Number) is sufficient.

> One might have expected something like the following to work:
> -type my_bitstring() :: <<_:16, _:_*3>>.
> prop_foo() -> ?FORALL(B, my_bitstring(), true).
> But PropEr will currently reject this for unit values other than 1 and 8,
> because I suck at predicting what features people will want to use, and
> thought this was a safe one to skip.

As said, I am only interested in full-byte binaries. So it was indeed
safe for this case.

Until 15 minutes ago how PropEr creates type instances was truly magic
for me. Now Eureka! For ones that are curious how it works:

x() ->
    ?FORALL(S, integer(0, 1023), S < 100).

translates to:
x() ->
    proper:forall(S, fun(S) -> integer(0, 1023) end)).

So we have a closure which tries to execute the nonsense (that's what
I thought for more than a year).

After a lot of tracing I found out that this closure is executed in
context of `proper_types` moduke, which *has* a function integer(Low,
High). That's it. That function returnsa a nothing-magic tuple, and is
able to proceed.

And now answering my question. binary/1 is defined in proper_types. :)
All makes sense now.

[1]: http://proper.softlab.ntua.gr/papers/proper_types.pdf

Motiejus Jakštys

More information about the erlang-questions mailing list