UNPKG

1.74 kBJavaScriptView Raw
1"use strict";
2
3var show = require("./show.js");
4
5/**
6 ### Arbitrary data
7*/
8
9// Blessing: i.e adding prototype
10/* eslint-disable no-use-before-define */
11function arbitraryProtoSMap(f, g, newShow) {
12 /* jshint validthis:true */
13 var arb = this;
14 return arbitraryBless({
15 generator: arb.generator.map(f),
16 shrink: arb.shrink.smap(f, g),
17 show: newShow || show.def
18 });
19}
20/* eslint-enable no-use-before-define */
21
22/**
23 - `.smap(f: a -> b, g: b -> a, newShow: (b -> string)?): arbitrary b`
24
25 Transform `arbitrary a` into `arbitrary b`. For example:
26
27 `g` should be a [right inverse](http://en.wikipedia.org/wiki/Surjective_function#Surjections_as_right_invertible_functions) of `f`, but doesn't need to be complete inverse.
28 i.e. i.e. `f` doesn't need to be invertible, only surjective.
29
30 ```js
31 var positiveIntegersArb = nat.smap(
32 function (x) { return x + 1; },
33 function (x) { return x - 1; });
34 ```
35
36 ```js
37 var setNatArb = jsc.array(jsc.nat).smap(_.uniq, _.identity);
38 ```
39
40 Right inverse means that *f(g(y)) = y* for all *y* in *Y*. Here *Y* is a type of **arrays of unique natural numbers**. For them
41 ```js
42 _.uniq(_.identity(y)) = _.uniq(y) = y
43 ```
44
45 Opposite: *g(f(x))* for all *x* in *X*, doesn't need to hold. *X* is **arrays of natural numbers**:
46 ```js
47 _.identity(_uniq([0, 0])) = [0]] != [0, 0]
48 ```
49
50 We need an inverse for shrinking, and there right inverse is enough. We can always *pull back* `smap`ped value and shrink the preimage, and *map* or *push forward* shrinked preimages again.
51*/
52function arbitraryBless(arb) {
53 arb.smap = arbitraryProtoSMap;
54 return arb;
55}
56
57module.exports = arbitraryBless;