Skip to content

Commit

Permalink
Merge 01f2143 into 6358b68
Browse files Browse the repository at this point in the history
  • Loading branch information
evilsoft committed Jul 22, 2019
2 parents 6358b68 + 01f2143 commit dc93a21
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 73 deletions.
6 changes: 3 additions & 3 deletions src/Pair/writerToPair.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ test('writerToPair with Writer', t => {
const value = 'something'
const log = 'log'

const p = writerToPair(Writer(log, value))
const p = writerToPair(Writer(Last(log), value))

t.ok(isSameType(Pair, p), 'returns a Pair')

Expand All @@ -54,7 +54,7 @@ test('writerToPair with Writer returning function', t => {
const value = 'something'
const log = 'log'

t.ok(isFunction(constant(writerToPair(Writer(log, value)))), 'returns a function')
t.ok(isFunction(constant(writerToPair(Writer(Last(log), value)))), 'returns a function')

const f = bindFunc(writerToPair(identity))

Expand All @@ -71,7 +71,7 @@ test('writerToPair with Writer returning function', t => {
t.throws(f({}), err, 'throws if function returns an object')

const lift =
x => Writer(log, x)
x => Writer(Last(log), x)

const p = writerToPair(lift, value)

Expand Down
134 changes: 75 additions & 59 deletions src/Writer/Writer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const Writer = _Writer(Last)
test('Writer construction', t => {
const w = bindFunc(_Writer)

const err = /Writer: Monoid required for construction/
const err = /^TypeError: Writer: Argument must be a Monoid Constructor/
t.throws(w(undefined), err, 'throws with undefined')
t.throws(w(null), err, 'throws with null')
t.throws(w(0), err, 'throws with falsey number')
Expand All @@ -46,27 +46,39 @@ test('Writer construction', t => {
})

test('Writer', t => {
const w = Writer(0, 0)
const w = Writer(Last(0), 0)
const f = bindFunc(Writer)

t.ok(isFunction(Writer), 'is a function')
t.ok(isObject(w), 'returns an object')

t.equals(Writer(0, 0).constructor, Writer, 'provides TypeRep on constructor')
t.equals(Writer(Last(0), 0).constructor, Writer, 'provides TypeRep on constructor')

t.ok(isFunction(Writer.of), 'provides an of function')
t.ok(isFunction(Writer.type), 'provides a type function')
t.ok(isString(Writer['@@type']), 'provides a @@type string')

const err = /Writer: Log entry and a value required/
const err = /^TypeError: Writer: Must be contructed with both a log entry and a value/
t.throws(f(), err, 'throws with no parameters')
t.throws(f(0), err, 'throws with one parameter')

const entryErr = /^TypeError: Writer: Log enrty must be an instance of Last/
t.throws(f(undefined, 0), entryErr, 'throws with undefined entry')
t.throws(f(null, 0), entryErr, 'throws with null entry')
t.throws(f(0, 0), entryErr, 'throws with falsy number entry')
t.throws(f(1, 0), entryErr, 'throws with truthy number entry')
t.throws(f('', 0), entryErr, 'throws with falsy string entry')
t.throws(f('string', 0), entryErr, 'throws with truthy string entry')
t.throws(f(false, 0), entryErr, 'throws with false entry')
t.throws(f(true, 0), entryErr, 'throws with true entry')
t.throws(f([], 0), entryErr, 'throws with array entry')
t.throws(f({}, 0), entryErr, 'throws with object entry')

t.end()
})

test('Writer fantasy-land api', t => {
const m = Writer(0, 0)
const m = Writer(Last(0), 0)

t.ok(isFunction(Writer[fl.of]), 'provides of function on constructor')

Expand All @@ -91,7 +103,7 @@ test('Writer @@implements', t => {
})

test('Writer inspect', t => {
const m = Writer(0, 0)
const m = Writer(Last(0), 0)

t.ok(isFunction(m.inspect), 'provides an inspect function')
t.equal(m.inspect, m.toString, 'toString is the same function as inspect')
Expand All @@ -101,28 +113,28 @@ test('Writer inspect', t => {
})

test('Writer type', t => {
const m = Writer(0, 0)
const m = Writer(Last(0), 0)

t.ok(isFunction(m.type), 'is a function')
t.equal(Writer.type, m.type, 'static and instance versions are the same')
t.equal(m.type(), 'Writer( Last )', 'returns Writer with Monoid Type')
t.equal(m.type(), 'Writer(Last)', 'returns Writer with Monoid Type')

t.end()
})

test('Writer @@type', t => {
const m = Writer(0, 0)
const m = Writer(Last(0), 0)

t.equal(Writer['@@type'], m['@@type'], 'static and instance versions are the same')
t.equal(m['@@type'], 'crocks/Writer@2( crocks/Last@1 )', 'returns crocks/Writer@2 with Monoid Type')
t.equal(m['@@type'], 'crocks/Writer@3( crocks/Last@1 )', 'returns crocks/Writer@3 with Monoid Type')

t.end()
})

test('Writer read', t => {
const x = 'some value'
const l = 'some log'
const m = Writer(l, x)
const m = Writer(Last(l), x)

t.ok(isFunction(m.read), 'is a function')
t.ok(isSameType(Pair, m.read()), 'returns a Pair')
Expand All @@ -135,7 +147,7 @@ test('Writer read', t => {

test('Writer valueOf', t => {
const x = 34
const w = Writer(0, x)
const w = Writer(Last(0), x)

t.ok(isFunction(w.valueOf), 'is a function')
t.equal(w.valueOf(), x, 'provides wrapped value')
Expand All @@ -145,7 +157,7 @@ test('Writer valueOf', t => {

test('Writer log', t => {
const x = 'log entry'
const w = Writer(x, 0)
const w = Writer(Last(x), 0)

t.ok(isFunction(w.log), 'is a function')
t.equal(w.log().type(), 'Last', 'returns a monoid')
Expand All @@ -155,9 +167,9 @@ test('Writer log', t => {
})

test('Writer equals functionality', t => {
const a = Writer(23, 0)
const b = Writer(15, 0)
const c = Writer(23, 1)
const a = Writer(Last(23), 0)
const b = Writer(Last(15), 0)
const c = Writer(Last(23), 1)

const value = 0
const nonWriter = { type: 'Writer...Not' }
Expand All @@ -171,10 +183,10 @@ test('Writer equals functionality', t => {
})

test('Writer equals properties (Setoid)', t => {
const a = Writer('seg', 0)
const b = Writer(false, 0)
const c = Writer(null, 1)
const d = Writer(3, 0)
const a = Writer(Last('seg'), 0)
const b = Writer(Last(false), 0)
const c = Writer(Last(null), 1)
const d = Writer(Last(3), 0)

t.ok(isFunction(a.equals), 'provides an equals function')
t.equals(a.equals(a), true, 'reflexivity')
Expand All @@ -186,9 +198,9 @@ test('Writer equals properties (Setoid)', t => {
})

test('Writer map errors', t => {
const map = bindFunc(Writer(0, 0).map)
const map = bindFunc(Writer(Last(0), 0).map)

const err = /Writer.map: Function required/
const err = /^TypeError: Writer.map: Function required/
t.throws(map(undefined), err, 'throws with undefined')
t.throws(map(null), err, 'throws with null')
t.throws(map(0), err, 'throws with falsey number')
Expand All @@ -206,9 +218,9 @@ test('Writer map errors', t => {
})

test('Writer map fantasy-land errors', t => {
const map = bindFunc(Writer(0, 0)[fl.map])
const map = bindFunc(Writer(Last(0), 0)[fl.map])

const err = /Writer.fantasy-land\/map: Function required/
const err = /^TypeError: Writer.fantasy-land\/map: Function required/
t.throws(map(undefined), err, 'throws with undefined')
t.throws(map(null), err, 'throws with null')
t.throws(map(0), err, 'throws with falsey number')
Expand All @@ -230,9 +242,9 @@ test('Writer map functionality', t => {
const x = 42
const l = 'log'

const m = Writer(l, x).map(spy)
const m = Writer(Last(l), x).map(spy)

t.equal(m.type(), 'Writer( Last )', 'returns a Writer')
t.ok(isSameType(Writer, m), 'returns a Writer')
t.equal(spy.called, true, 'calls mapping function')
t.equal(m.valueOf(), x, 'returns the result of the map inside of new Writer, on value key')
t.same(m.log().valueOf(), l, 'returns the result of the map inside of new Writer, on log key')
Expand All @@ -243,7 +255,7 @@ test('Writer map functionality', t => {
})

test('Writer map properties (Functor)', t => {
const m = Writer('blop', 49)
const m = Writer(Last('blop'), 49)

const f = x => x + 54
const g = x => x * 4
Expand All @@ -260,13 +272,13 @@ test('Writer ap errors', t => {
const m = { type: () => 'Writer...Not' }

const ap =
bindFunc(Writer(0, unit).ap)
bindFunc(Writer(Last(0), unit).ap)

const wrapAp = bindFunc(
x => Writer(0, x).ap(Writer(0, 0))
x => Writer(Last(0), x).ap(Writer(Last(0), 0))
)

const noFunc = /Writer.ap: Wrapped value must be a function/
const noFunc = /^TypeError: Writer.ap: Wrapped value must be a function/
t.throws(wrapAp(undefined), noFunc, 'throws when wrapped value is undefined')
t.throws(wrapAp(null), noFunc, 'throws when wrapped value is null')
t.throws(wrapAp(0), noFunc, 'throws when wrapped value is a falsey number')
Expand All @@ -278,7 +290,7 @@ test('Writer ap errors', t => {
t.throws(wrapAp([]), noFunc, 'throws when wrapped value is an array')
t.throws(wrapAp({}), noFunc, 'throws when wrapped value is an object')

const err = /Writer.ap: Writer required/
const err = /^TypeError: Writer.ap: Writer required/
t.throws(ap(undefined), err, 'throws with undefined')
t.throws(ap(null), err, 'throws with null')
t.throws(ap(0), err, 'throws with falsey number')
Expand All @@ -291,28 +303,32 @@ test('Writer ap errors', t => {
t.throws(ap({}), err, 'throws with an object')
t.throws(ap(m), err, 'throws with Non-Writer')

t.doesNotThrow(ap(Writer(0, 0)), 'allows a Writer')
t.doesNotThrow(ap(Writer(Last(0), 0)), 'allows a Writer')

t.end()
})

test('Writer ap properties (Apply)', t => {
const m = Writer(0, identity)
const m = Writer(Last(0), identity)

const a = m.map(compose).ap(m).ap(m)
const b = m.ap(m.ap(m))

t.ok(isFunction(m.map), 'implements the Functor spec')
t.ok(isFunction(m.ap), 'provides an ap function')

t.equal(a.ap(Writer(0, 3)).valueOf(), b.ap(Writer(0, 3)).valueOf(), 'composition')
t.equal(
a.ap(Writer(Last(0), 3)).valueOf(),
b.ap(Writer(Last(0), 3)).valueOf(),
'composition'
)

t.end()
})

test('Writer ap functionality', t => {
const a = Writer(0, x => x + 2)
const b = Writer(1, 27)
const a = Writer(Last(0), x => x + 2)
const b = Writer(Last(1), 27)

t.same(a.ap(b).log().valueOf(), 1, 'concats applied Writers log to inital log')
t.equal(a.ap(b).valueOf(), 29, 'applys applied value to function')
Expand All @@ -323,22 +339,22 @@ test('Writer ap functionality', t => {
test('Writer of', t => {
const w = Writer.of(0)

t.equal(Writer.of, Writer(0, 0).of, 'Writer.of is the same as the instance version')
t.equal(Writer.of, Writer(Last(0), 0).of, 'Writer.of is the same as the instance version')

t.equal(w.type(), 'Writer( Last )', 'returns an Writer')
t.ok(isSameType(Writer, w), 'returns a Writer')
t.equal(w.valueOf(), 0, 'wraps the value passed into a Writer')
t.same(w.log().valueOf(), Last.empty().valueOf(), 'provides an empty Monoid as the log')

t.end()
})

test('Writer of properties (Applicative)', t => {
const m = Writer(0, identity)
const m = Writer(Last(0), identity)

t.ok(isFunction(m.of), 'provides an of function')
t.ok(isFunction(m.ap), 'implements the Apply spec')

t.equal(m.ap(Writer(0, 3)).valueOf(), 3, 'identity')
t.equal(m.ap(Writer(Last(0), 3)).valueOf(), 3, 'identity')
t.equal(m.ap(Writer.of(3)).valueOf(), Writer.of(identity(3)).valueOf(), 'homomorphism')

const a = x => m.ap(Writer.of(x))
Expand All @@ -350,11 +366,11 @@ test('Writer of properties (Applicative)', t => {
})

test('Writer chain errors', t => {
const m = Writer(0, 0)
const m = Writer(Last(0), 0)
const chain = bindFunc(m.chain)
const fn = x => Writer(0, x)
const fn = x => Writer(Last(0), x)

const err = /Writer.chain: Function required/
const err = /^TypeError: Writer.chain: Function required/
t.throws(chain(undefined), err, 'throws with undefined')
t.throws(chain(null), err, 'throws with null')
t.throws(chain(0), err, 'throws with falsey number')
Expand All @@ -366,7 +382,7 @@ test('Writer chain errors', t => {
t.throws(chain([]), err, 'throws with an array')
t.throws(chain({}), err, 'throws with an object')

const noWriter = /Writer.chain: Function must return a Writer/
const noWriter = /^TypeError: Writer.chain: Function must return a Writer/
t.throws(chain(unit), noWriter, 'throws with non-Writer returning function')

t.doesNotThrow(chain(fn), 'allows a Writer returning function')
Expand All @@ -375,11 +391,11 @@ test('Writer chain errors', t => {
})

test('Writer chain fantasy-land errors', t => {
const m = Writer(0, 0)
const m = Writer(Last(0), 0)
const chain = bindFunc(m[fl.chain])
const fn = x => Writer(0, x)
const fn = x => Writer(Last(0), x)

const err = /Writer.fantasy-land\/chain: Function required/
const err = /^TypeError: Writer.fantasy-land\/chain: Function required/
t.throws(chain(undefined), err, 'throws with undefined')
t.throws(chain(null), err, 'throws with null')
t.throws(chain(0), err, 'throws with falsey number')
Expand All @@ -391,7 +407,7 @@ test('Writer chain fantasy-land errors', t => {
t.throws(chain([]), err, 'throws with an array')
t.throws(chain({}), err, 'throws with an object')

const noWriter = /Writer.fantasy-land\/chain: Function must return a Writer/
const noWriter = /^TypeError: Writer.fantasy-land\/chain: Function must return a Writer/
t.throws(chain(unit), noWriter, 'throws with non-Writer returning function')

t.doesNotThrow(chain(fn), 'allows a Writer returning function')
Expand All @@ -400,8 +416,8 @@ test('Writer chain fantasy-land errors', t => {
})

test('Writer chain functionality', t => {
const m = Writer(0, 45)
const fn = x => Writer(1, x + 2)
const m = Writer(Last(0), 45)
const fn = x => Writer(Last(1), x + 2)

t.same(m.chain(fn).log().valueOf(), 1, 'concats chained log to initial log')
t.equal(m.chain(fn).valueOf(), 47, 'applys function to wrapped value')
Expand All @@ -410,25 +426,25 @@ test('Writer chain functionality', t => {
})

test('Writer chain properties (Chain)', t => {
t.ok(isFunction(Writer(0, 0).chain), 'provides a chain function')
t.ok(isFunction(Writer(0, 0).ap), 'implements the Apply spec')
t.ok(isFunction(Writer(Last(0), 0).chain), 'provides a chain function')
t.ok(isFunction(Writer(Last(0), 0).ap), 'implements the Apply spec')

const f = x => Writer(1, x + 2)
const g = x => Writer(2, x + 10)
const f = x => Writer(Last(1), x + 2)
const g = x => Writer(Last(2), x + 10)

const a = x => Writer(0, x).chain(f).chain(g)
const b = x => Writer(0, x).chain(y => f(y).chain(g))
const a = x => Writer(Last(0), x).chain(f).chain(g)
const b = x => Writer(Last(0), x).chain(y => f(y).chain(g))

t.equal(a(10).valueOf(), b(10).valueOf(), 'assosiativity')

t.end()
})

test('Writer chain properties (Monad)', t => {
t.ok(isFunction(Writer(1, 0).chain), 'implements the Chain spec')
t.ok(isFunction(Writer(2, 0).of), 'implements the Applicative spec')
t.ok(isFunction(Writer(Last(1), 0).chain), 'implements the Chain spec')
t.ok(isFunction(Writer(Last(2), 0).of), 'implements the Applicative spec')

const f = x => Writer(0, x)
const f = x => Writer(Last(0), x)

t.equal(Writer.of(3).chain(f).valueOf(), f(3).valueOf(), 'left identity')
t.equal(f(3).chain(Writer.of).valueOf(), f(3).valueOf(), 'right identity')
Expand Down

0 comments on commit dc93a21

Please sign in to comment.