describe('concat', function(){
  it('is associative',
    claire.forAll(validGen, validGen, validGen).satisfy(function(v1, v2, v3){
      assert.deepEqual(v1.concat(v2.concat(v3)), v1.concat(v2).concat(v3));
      return true;
    }).asTest()
  );

  it('chooses the last of two success values',
    claire.forAll(successGen, successGen).satisfy(function(s1, s2){
      assert.deepEqual(s1.concat(s2), s2);
      return true;
    }).asTest()
  );

  it('returns a failure over a success',
    claire.forAll(successGen, failureGen).satisfy(function(s, f){
      assert.deepEqual(s.concat(f), f);
      assert.deepEqual(f.concat(s), f);
      return true;
    }).asTest()
  );

  it('concats two failure values',
    claire.forAll(failureGen, failureGen).satisfy(function(f1, f2){
      assert.deepEqual(f1.concat(f2).value, f1.value.concat(f2.value));
      return true;
    }).asTest()
  );
});
Example #2
0
  describe('fromConnectionsList', function(){
    var g;
    it('has as many edges as pairs passed',
      claire.forAll(PairList).satisfy(function(pairs){
        g = graph.fromConnectionsList(pairs);
        assert.equal(g.nedges, pairs.length);
        return true;
      }).asTest()
    );

    it('has as many vertices as the max vertex passed',
      claire.forAll(PairList).satisfy(function(pairs){
        g = graph.fromConnectionsList(pairs);
        if(pairs.length){
          assert.equal(g.nvertices, _.max(_.flatten(pairs)));
        }
        else {
          assert.equal(g.nvertices, 0);
        }
        return true;
      }).asTest()
    );

    it('produces the right adjacency lists', function(){
      var pairs = [[0,1], [1,2], [1,3],[2,1], [3,0], [0, 4]];
      var g = graph.fromConnectionsList(pairs);
      _.each(pairs, function(pair) {
        assert(
          list.any(function(edge){return edge.y === pair[1];}, g.edges[pair[0]])
        );
      });
    });
  });
describe('traverse', function(){
  function arrayToMaybe(a){return a.length ? some(a[0]) : none};
  function maybeToArray(m){return m.isJust ? [m.value]  : []  };
  function idToArray(i){return [i.value]};
  function idToMaybe(i){return some(i.value)};
  function idToValid(i){return Success(i.value)};
  function arrayToValid(a){return a.length ? Success(a[0]) : Failure(['empty'])}
  function maybeToValid(m){return m.isJust ? Success(m.value)
    : Failure(['empty']); };
  var transformGen = claire.choice(
    {t: arrayToMaybe, i: Array.of, o: some},
    {t: maybeToArray, i: some, o: Array.of},
    {t: idToArray, i: Id, o: Array.of},
    {t: idToMaybe, i: Id, o: some},
    {t: idToValid, i: Id, o: Success},
    {t: arrayToValid, i: Array.of, o: Success},
    {t: maybeToValid, i: some, o: Success}
  );
  //wrapping because of generator issue in interchange comment
  var fGen = claire.choice([drop1], [isEmpty], [arrayToMaybe],
    [function(a){return a.length;}]);

  it('obeys naturality',
    claire.forAll(transformGen, fGen, validGen).satisfy(function(t, f, v){
      var apF = B(t.i)(f[0]);
      assert.deepEqual(t.t(v.traverse(apF, t.i)),
        v.traverse(B(t.t)(apF), t.o));
      return true;
    }).asTest()
  );

  it('obeys identity', claire.forAll(validGen).satisfy(function(v){
    assert.deepEqual(v.traverse(Id, Id), Id(v));
    return true;
  }).asTest());

  var _ = require('lodash');
  function ComposeF(nestedFs){
    if(this instanceof ComposeF){
      this.value = nestedFs;
    } else { return new ComposeF(nestedFs) }
  };
  ComposeF.prototype.map = function(f){
    return new ComposeF(this.value.map(function(x){return x.map(f)}));
  };
  it('obeys composition', claire.forAll(validGen).satisfy(function(v){
    var a = v.traverse(function(a){return ComposeF(drop1(a).map(some))},
      function(x){return ComposeF(Array.of(some(x)))}
    );
    var b = ComposeF(v.traverse(drop1, Array.of).map(function(x){return x.traverse(some, some)}));
    assert.deepEqual(a, b);
    return true;
  }).asTest());
});
describe('ap', function(){
  it('obeys homomorphism', claire.forAll(val).satisfy(function(x){
    assert.deepEqual(Success(drop1).ap(Success(x)), Success(drop1(x)));
    return true;
  }).asTest());

  it('obeys interchange',
    //wrap success and failure in arrays, otherwise claire treats them as
    //generators and invokes them with a size hint to get a value.
    claire.forAll(claire.choice([Success], [Failure]), val).satisfy(function(c, x){
      var u = c[0](drop1);
      assert.deepEqual(u.ap(Success(x)), Success(function(f){return f(x)}).ap(u));
      return true;
    }).asTest()
  );
});
describe('chain', function(){
  var mDrop1 = B(Success)(drop1);
  var mEmpty = B(Success)(isEmpty);

  it('is associative', claire.forAll(validGen).satisfy(function(v){
    assert.deepEqual(v.chain(mDrop1).chain(mEmpty),
      v.chain(function(x){return mDrop1(x).chain(mEmpty)})
    );
    return true;
  }).asTest());

  it('has left identity', claire.forAll(val).satisfy(function(x){
    assert.deepEqual(Success(x).chain(mDrop1), mDrop1(x));
    return true;
  }).asTest());

  it('has right identity', claire.forAll(validGen).satisfy(function(v){
    assert.deepEqual(v.chain(Success), v);
    return true;
  }).asTest());
});
describe('map', function(){
  it('obeys identity', claire.forAll(validGen).satisfy(function(v){
    assert.deepEqual(v.map(I), v);
    return true;
  }).asTest());

  it('obeys composition', claire.forAll(validGen).satisfy(function(v){
    assert.deepEqual(v.map(B(isEmpty)(drop1)), v.map(drop1).map(isEmpty));
    return true;
  }).asTest());


  it('maps the inner value of a success',
    claire.forAll(successGen).satisfy(function(s){
      assert.deepEqual(s.map(drop1).value, drop1(s.value));
      return true;
    }).asTest()
  );

  it('is no-op with a failure', claire.forAll(failureGen).satisfy(function(f){
    assert.deepEqual(f.map(drop1).value, f.value);
    return true;
  }).asTest());
});
Example #7
0
'use strict'
var gen = require('./generators')
var forall = require('claire').forAll

module.exports = {
  ints: {
    add: {
      assoc: forall(gen.Int, gen.Int, gen.Int).satisfy(function(x, y, z){
        return (x+y)+z === x+(y+z)
      })
      ,commute: forall(gen.Int, gen.Int).satisfy(function(x, y) {
        return x+y === y+x
      })
      ,ident: forall(gen.Int).satisfy(function(x) {
        return x+0 === x
      })
      ,closure: forall(gen.Int, gen.Int).satisfy(function(x, y){
        return x+y === Math.floor(x+y)
      })
    }
    ,mul: {
      assoc: forall(gen.Int, gen.Int, gen.Int).satisfy(function(x, y, z){
        return (x*y)*z === x*(y*z)
      })
      ,commute: forall(gen.Int, gen.Int).satisfy(function(x, y) {
        return x*y === y*x
      })
      ,ident: forall(gen.Int).satisfy(function(x) {
        return x*1 === x
      })
      ,closure: forall(gen.Int, gen.Int).satisfy(function(x, y){