Skip to content

Commit

Permalink
Add the Last Monoid (#130)
Browse files Browse the repository at this point in the history
* 🔧 typo in specs `Semigoup`

* add Last Monoid and transformations
  • Loading branch information
evilsoft authored Jul 1, 2017
1 parent dc261f3 commit d3a32ad
Show file tree
Hide file tree
Showing 29 changed files with 1,153 additions and 12 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ All `Monoids` provide `empty` and `type` function on their Constructors as well
| `Any` | Boolean | Logical OR | `false` |
| `Assign` | Object | `Object.assign` | `{}` |
| `Endo` | Function | `compose` | `identity` |
| `Last` | Maybe | Last `Just` | `Nothing` |
| `Max` | Number | `Math.max` | `-Infinity` |
| `Min` | Number | `Math.min` | `Infinity` |
| `Prod` | Number | Multiplication | `1` |
Expand Down Expand Up @@ -860,12 +861,19 @@ bad
|---|---|---|
| `arrayToList` | `[ a ] -> List a` | `(a -> [ b ]) -> a -> List b` |
| `eitherToAsync` | `Either e a -> Async e a` | `(a -> Either e b) -> a -> Async e b` |
| `eitherToLast` | `Either b a -> Last a` | `(a -> Either c b) -> a -> Last b` |
| `eitherToMaybe` | `Either b a -> Maybe a` | `(a -> Either c b) -> a -> Maybe b` |
| `eitherToResult` | `Either e a -> Result e a` | `(a -> Either e b) -> a -> Result e b` |
| `lastToAsync` | `e -> Last a -> Async e a` | `e -> (a -> Last b) -> a -> Last e b` |
| `lastToEither` | `c -> Last a -> Either c a` | `c -> (a -> Last b) -> a -> Either c b` |
| `lastToMaybe` | `Last a -> Maybe a` | `(a -> Last b) -> a -> Maybe b` |
| `lastToResult` | `c -> Last a -> Result c a` | `c -> (a -> Last b) -> a -> Result c b` |
| `listToArray` | `List a -> [ a ]` | `(a -> List b) -> a -> [ b ]` |
| `maybeToAsync` | `e -> Maybe a -> Async e a` | `e -> (a -> Maybe b) -> a -> Async e b` |
| `maybeToEither` | `c -> Maybe a -> Either c a` | `c -> (a -> Maybe b) -> a -> Either c b` |
| `maybeToLast` | `Maybe a -> Last a` | `(a -> Maybe b) -> a -> Last b` |
| `maybeToResult` | `c -> Maybe a -> Result c a` | `c -> (a -> Maybe b) -> a -> Result c b` |
| `resultToAsync` | `Result e a -> Async e a` | `(a -> Result e b) -> a -> Async e b` |
| `resultToEither` | `Result e a -> Either e a` | `(a -> Result e b) -> a -> Either e b` |
| `resultToMaybe` | `Result b a -> Maybe a` | `(a -> Result c b) -> a -> Maybe b` |
| `resultToLast` | `Result e a -> Last a` | `(a -> Result e b) -> a -> Last b` |
| `resultToMaybe` | `Result e a -> Maybe a` | `(a -> Result e b) -> a -> Maybe b` |
8 changes: 8 additions & 0 deletions crocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const monoids = {
Any: require('./monoids/Any'),
Assign: require('./monoids/Assign'),
Endo: require('./monoids/Endo'),
Last: require('./monoids/Last'),
Min: require('./monoids/Min'),
Max: require('./monoids/Max'),
Prod: require('./monoids/Prod'),
Expand Down Expand Up @@ -168,14 +169,21 @@ const predicates = {
const transforms = {
arrayToList: require('./transforms/arrayToList'),
eitherToAsync: require('./transforms/eitherToAsync'),
eitherToLast: require('./transforms/eitherToLast'),
eitherToMaybe: require('./transforms/eitherToMaybe'),
eitherToResult: require('./transforms/eitherToResult'),
lastToAsync: require('./transforms/lastToAsync'),
lastToEither: require('./transforms/lastToEither'),
lastToMaybe: require('./transforms/lastToMaybe'),
lastToResult: require('./transforms/lastToResult'),
listToArray: require('./transforms/listToArray'),
maybeToAsync: require('./transforms/maybeToAsync'),
maybeToEither: require('./transforms/maybeToEither'),
maybeToLast: require('./transforms/maybeToLast'),
maybeToResult: require('./transforms/maybeToResult'),
resultToAsync: require('./transforms/resultToAsync'),
resultToEither: require('./transforms/resultToEither'),
resultToLast: require('./transforms/resultToLast'),
resultToMaybe: require('./transforms/resultToMaybe')
}

Expand Down
16 changes: 16 additions & 0 deletions crocks.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ const All = require('./monoids/All')
const Any = require('./monoids/Any')
const Assign = require('./monoids/Assign')
const Endo = require('./monoids/Endo')
const Last = require('./monoids/Last')
const Min = require('./monoids/Min')
const Max = require('./monoids/Max')
const Prod = require('./monoids/Prod')
Expand Down Expand Up @@ -155,14 +156,21 @@ const isTraversable = require('./predicates/isTraversable')

const arrayToList = require('./transforms/arrayToList')
const eitherToAsync = require('./transforms/eitherToAsync')
const eitherToLast = require('./transforms/eitherToLast')
const eitherToMaybe = require('./transforms/eitherToMaybe')
const eitherToResult = require('./transforms/eitherToResult')
const lastToAsync = require('./transforms/lastToAsync')
const lastToEither = require('./transforms/lastToEither')
const lastToMaybe = require('./transforms/lastToMaybe')
const lastToResult = require('./transforms/lastToResult')
const listToArray = require('./transforms/listToArray')
const maybeToAsync = require('./transforms/maybeToAsync')
const maybeToEither = require('./transforms/maybeToEither')
const maybeToLast = require('./transforms/maybeToLast')
const maybeToResult = require('./transforms/maybeToResult')
const resultToAsync = require('./transforms/resultToAsync')
const resultToEither = require('./transforms/resultToEither')
const resultToLast = require('./transforms/resultToLast')
const resultToMaybe = require('./transforms/resultToMaybe')

test('entry', t => {
Expand Down Expand Up @@ -274,6 +282,7 @@ test('entry', t => {
t.equal(crocks.Any, Any, 'provides the Any monoid')
t.equal(crocks.Assign, Assign, 'provides the Assign monoid')
t.equal(crocks.Endo, Endo, 'provides the Endo monoid')
t.equal(crocks.Last, Last, 'provides the Last monoid')
t.equal(crocks.Min, Min, 'provides the Min monoid')
t.equal(crocks.Max, Max, 'provides the Max monoid')
t.equal(crocks.Prod, Prod, 'provides the Prod monoid')
Expand Down Expand Up @@ -322,13 +331,20 @@ test('entry', t => {
t.equal(crocks.arrayToList, arrayToList, 'provides the arrayToList function')
t.equal(crocks.eitherToAsync, eitherToAsync, 'provides the eitherToAsync function')
t.equal(crocks.eitherToMaybe, eitherToMaybe, 'provides the eitherToMaybe function')
t.equal(crocks.eitherToLast, eitherToLast, 'provides the eitherToLast function')
t.equal(crocks.eitherToResult, eitherToResult, 'provides the eitherToResult function')
t.equal(crocks.lastToAsync, lastToAsync, 'provides the lastToAsync function')
t.equal(crocks.lastToEither, lastToEither, 'provides the lastToEither function')
t.equal(crocks.lastToMaybe, lastToMaybe, 'provides the lastToMaybe function')
t.equal(crocks.lastToResult, lastToResult, 'provides the lastToResult function')
t.equal(crocks.listToArray, listToArray, 'provides the listToArray function')
t.equal(crocks.maybeToAsync, maybeToAsync, 'provides the maybeToAsync function')
t.equal(crocks.maybeToEither, maybeToEither, 'provides the maybeToEither function')
t.equal(crocks.maybeToLast, maybeToLast, 'provides the maybeToLast function')
t.equal(crocks.maybeToResult, maybeToResult, 'provides the maybeToResult function')
t.equal(crocks.resultToAsync, resultToAsync, 'provides the resultToAsync function')
t.equal(crocks.resultToEither, resultToEither, 'provides the resultToEither function')
t.equal(crocks.resultToLast, resultToLast, 'provides the resultToLast function')
t.equal(crocks.resultToMaybe, resultToMaybe, 'provides the resultToMaybe function')

t.end()
Expand Down
2 changes: 1 addition & 1 deletion crocks/Const.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ test('Const equals properties (Setoid)', t => {
t.end()
})

test('Const concat properties (Semigoup)', t => {
test('Const concat properties (Semigroup)', t => {
const a = Const(0)
const b = Const(true)
const c = Const('')
Expand Down
2 changes: 1 addition & 1 deletion crocks/Either.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ test('Either concat functionality', t => {
t.end()
})

test('Either concat properties (Semigoup)', t => {
test('Either concat properties (Semigroup)', t => {
const extract =
either(identity, identity)

Expand Down
2 changes: 1 addition & 1 deletion crocks/Identity.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ test('Identity concat functionality', t => {
t.end()
})

test('Identity concat properties (Semigoup)', t => {
test('Identity concat properties (Semigroup)', t => {
const extract =
m => m.value()

Expand Down
2 changes: 1 addition & 1 deletion crocks/Maybe.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ test('Maybe concat functionality', t => {
t.end()
})

test('Maybe concat properties (Semigoup)', t => {
test('Maybe concat properties (Semigroup)', t => {
const extract =
either(constant('Nothing'), identity)

Expand Down
2 changes: 1 addition & 1 deletion crocks/Pred.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ test('Pred concat functionality', t => {
t.end()
})

test('Pred concat properties (Semigoup)', t => {
test('Pred concat properties (Semigroup)', t => {
const a = Pred(constant(false))
const b = Pred(constant(true))
const c = Pred(constant(false))
Expand Down
2 changes: 1 addition & 1 deletion crocks/Result.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ test('Result concat functionality', t => {
t.end()
})

test('Result concat properties (Semigoup)', t => {
test('Result concat properties (Semigroup)', t => {
const extract =
either(identity, identity)

Expand Down
2 changes: 1 addition & 1 deletion crocks/Unit.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ test('Unit equals properties (Setoid)', t => {
t.end()
})

test('Unit concat properties (Semigoup)', t => {
test('Unit concat properties (Semigroup)', t => {
const a = Unit(0)
const b = Unit(true)
const c = Unit('')
Expand Down
2 changes: 1 addition & 1 deletion monoids/All.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ test('All concat functionality', t => {
t.end()
})

test('All concat properties (Semigoup)', t => {
test('All concat properties (Semigroup)', t => {
const a = All(0)
const b = All(true)
const c = All('')
Expand Down
2 changes: 1 addition & 1 deletion monoids/Any.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ test('Any type', t => {
t.end()
})

test('Any concat properties (Semigoup)', t => {
test('Any concat properties (Semigroup)', t => {
const a = Any(0)
const b = Any(true)
const c = Any('')
Expand Down
73 changes: 73 additions & 0 deletions monoids/Last.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/** @license ISC License (c) copyright 2017 original and current authors */
/** @author Ian Hofmann-Hicks (evil) */

const _implements = require('../internal/implements')
const _inspect = require('../internal/inspect')

const constant = require('../combinators/constant')
const identity = require('../combinators/identity')
const isSameType = require('../predicates/isSameType')

const Maybe = require('../crocks/Maybe')

const _empty =
() => Last(Maybe.Nothing())

const _type =
constant('Last')

function Last(x) {
if(!arguments.length) {
throw new TypeError('Last: Requires one argument')
}

const maybe =
!isSameType(Maybe, x) ? Maybe.of(x) : x.map(identity)

const value =
constant(maybe)

const type =
_type

const empty =
_empty

const inspect =
constant(`Last(${_inspect(maybe)} )`)

const option =
maybe.option

function concat(m) {
if(!isSameType(Last, m)) {
throw new TypeError('Last.concat: Last required')
}

const n =
m.value().map(identity)

return Last(
maybe.either(
constant(n),
constant(n.either(constant(maybe), constant(n)))
)
)
}

return {
concat, empty, inspect, option, type, value
}
}

Last['@@implements'] = _implements(
[ 'concat', 'empty' ]
)

Last.empty =
_empty

Last.type =
_type

module.exports = Last
Loading

0 comments on commit d3a32ad

Please sign in to comment.