├── .gitattributes ├── docs ├── src │ ├── CNAME │ ├── wedeploy.json │ ├── images │ │ └── favicon.ico │ ├── site.json │ ├── partials │ │ ├── TutorialTimer.soy │ │ ├── SocialButtons.js │ │ ├── Sidebar.js │ │ └── SocialButtons.soy │ ├── styles │ │ ├── main.scss │ │ └── custom │ │ │ └── _landing.scss │ └── layouts │ │ └── main.soy ├── .gitignore ├── package.json └── README.md ├── index.js ├── .npmignore ├── src ├── core │ ├── _unit.js │ ├── isMap.js │ ├── isArray.js │ ├── isDefined.js │ ├── implements.js │ ├── isString.js │ ├── isSymbol.js │ ├── isFunction.js │ ├── isNil.js │ ├── isNumber.js │ ├── isBichain.js │ ├── isFunctor.js │ ├── isTypeRepOf.js │ ├── isDate.js │ ├── isFoldable.js │ ├── compose.js │ ├── isSame.js │ ├── isSemigroupoid.js │ ├── isContravariant.js │ ├── isObject.js │ ├── predOrFunc.js │ ├── isAlt.js │ ├── isInteger.js │ ├── isChain.js │ ├── isPromise.js │ ├── isApply.js │ ├── isIterable.js │ ├── isExtend.js │ ├── type.js │ ├── apOrFunc.js │ ├── isBifunctor.js │ ├── isMonad.js │ ├── isPlus.js │ ├── isSemigroup.js │ ├── isApplicative.js │ ├── isMonoid.js │ ├── once.js │ ├── mconcatMap.js │ ├── implements.spec.js │ ├── isPredOrFunc.js │ ├── isProfunctor.js │ ├── cloneIterable.js │ ├── hasAlg.js │ ├── curryN.js │ ├── isSameType.js │ ├── once.spec.js │ ├── predOrFunc.spec.js │ ├── compose.spec.js │ ├── isEmpty.js │ ├── mconcatMap.spec.js │ ├── flNames.js │ ├── innerConcat.js │ ├── type.spec.js │ ├── apOrFunc.spec.js │ ├── isString.spec.js │ ├── isArray.spec.js │ ├── isObject.spec.js │ ├── isDefined.spec.js │ ├── isTypeRepOf.spec.js │ ├── isNil.spec.js │ ├── isMap.spec.js │ ├── isDate.spec.js │ ├── isNumber.spec.js │ ├── isSymbol.spec.js │ ├── isFunction.spec.js │ └── flNames.spec.js ├── List │ ├── index.js │ ├── List.spec.js │ ├── arrayToList.js │ ├── listToArray.js │ └── maybeToList.js ├── Pair │ ├── index.js │ ├── Pair.spec.js │ ├── branch.js │ ├── fst.js │ ├── snd.js │ ├── toPairs.js │ ├── writerToPair.js │ └── fanout.js ├── Pred │ ├── index.js │ └── Pred.spec.js ├── Unit │ ├── index.js │ └── Unit.spec.js ├── Maybe │ ├── index.js │ ├── prop.js │ ├── propPath.js │ ├── Maybe.spec.js │ ├── safe.js │ ├── safeAfter.js │ ├── safeLift.js │ ├── maybeToArray.js │ ├── lastToMaybe.js │ ├── firstToMaybe.js │ ├── getProp.js │ ├── eitherToMaybe.js │ ├── resultToMaybe.js │ └── find.js ├── helpers │ ├── unit.js │ ├── assoc.js │ ├── dissoc.js │ ├── unit.spec.js │ ├── propOr.js │ ├── propPathOr.js │ ├── defaultTo.js │ ├── unary.js │ ├── once.js │ ├── binary.js │ ├── curry.js │ ├── objOf.js │ ├── assign.js │ ├── defaultProps.js │ ├── tap.js │ ├── partial.js │ ├── nAry.js │ ├── mconcat.js │ ├── mreduce.js │ ├── pipe.js │ ├── mapReduce.js │ ├── pipeS.js │ ├── omit.js │ ├── compose.js │ ├── pipeK.js │ ├── composeS.js │ ├── defaultTo.spec.js │ ├── liftA2.js │ ├── mconcatMap.js │ ├── mreduceMap.js │ ├── unary.spec.js │ ├── composeP.js │ ├── liftA3.js │ ├── once.spec.js │ ├── pipeP.js │ ├── getPropOr.js │ ├── pick.js │ ├── fromPairs.js │ ├── binary.spec.js │ └── composeK.js ├── predicates │ ├── isAlt.js │ ├── isApply.js │ ├── isArray.js │ ├── isChain.js │ ├── isEmpty.js │ ├── isMap.js │ ├── isMonad.js │ ├── isNil.js │ ├── isPlus.js │ ├── isDate.js │ ├── isDefined.js │ ├── isExtend.js │ ├── isFunctor.js │ ├── isInteger.js │ ├── isMonoid.js │ ├── isNumber.js │ ├── isObject.js │ ├── isPromise.js │ ├── isString.js │ ├── isSymbol.js │ ├── isBichain.js │ ├── isBifunctor.js │ ├── isFoldable.js │ ├── isFunction.js │ ├── isIterable.js │ ├── isProfunctor.js │ ├── isSameType.js │ ├── isSemigroup.js │ ├── isApplicative.js │ ├── isSemigroupoid.js │ ├── isContravariant.js │ ├── isFunction.spec.js │ ├── isAlt.spec.js │ ├── isMap.spec.js │ ├── isNil.spec.js │ ├── isApply.spec.js │ ├── isFalsy.js │ ├── isPlus.spec.js │ ├── isSame.js │ ├── isSame.spec.js │ ├── isArray.spec.js │ ├── isChain.spec.js │ ├── isDate.spec.js │ ├── isEmpty.spec.js │ ├── isMonad.spec.js │ ├── isTrue.js │ ├── isTruthy.js │ ├── isExtend.spec.js │ ├── isFalse.js │ ├── isInteger.spec.js │ ├── isMonoid.spec.js │ ├── isNumber.spec.js │ ├── isObject.spec.js │ ├── isString.spec.js │ ├── isSymbol.spec.js │ ├── propPathSatisfies.js │ ├── isBichain.spec.js │ ├── isDefined.spec.js │ ├── isFunctor.spec.js │ ├── isPromise.spec.js │ ├── propPathEq.js │ ├── isFoldable.spec.js │ ├── isSameType.spec.js │ ├── isBifunctor.spec.js │ ├── isBoolean.js │ ├── isSemigroup.spec.js │ ├── isApplicative.spec.js │ ├── isContravariant.spec.js │ ├── isProfunctor.spec.js │ ├── isSemigroupoid.spec.js │ ├── isSetoid.js │ ├── isAlternative.js │ ├── isIterable.spec.js │ ├── isTraversable.js │ ├── isCategory.js │ ├── hasProp.js │ ├── propEq.js │ ├── isTrue.spec.js │ ├── isFalse.spec.js │ ├── isBoolean.spec.js │ └── propSatisfies.js ├── logic │ ├── index.js │ ├── not.js │ ├── and.js │ ├── or.js │ ├── implies.js │ ├── index.spec.js │ ├── when.js │ ├── unless.js │ └── ifElse.js ├── combinators │ ├── identity.js │ ├── constant.js │ ├── identity.spec.js │ ├── index.js │ ├── applyTo.js │ ├── flip.js │ ├── psi.js │ ├── compose2.js │ ├── converge.js │ ├── substitution.js │ └── composeB.js ├── pointfree │ ├── valueOf.js │ ├── equals.js │ ├── run.js │ ├── option.js │ ├── compareWith.js │ ├── runWith.js │ ├── cons.js │ ├── merge.js │ ├── alt.js │ ├── concat.js │ ├── reduceRight.js │ ├── fold.js │ ├── either.js │ ├── swap.js │ ├── coalesce.js │ ├── tail.js │ ├── init.js │ ├── bichain.js │ ├── extend.js │ ├── both.js │ ├── reduce.js │ ├── ap.js │ ├── bimap.js │ ├── first.js │ ├── second.js │ ├── empty.js │ ├── promap.js │ ├── sequence.js │ ├── chain.js │ ├── foldMap.js │ ├── contramap.js │ ├── head.js │ ├── filter.js │ ├── traverse.js │ ├── valueOf.spec.js │ ├── last.js │ └── reject.js ├── Writer │ ├── log.js │ └── read.js ├── Tuple │ ├── project.js │ └── tupleToArray.js ├── State │ ├── evalWith.js │ └── execWith.js ├── Async │ ├── race.js │ ├── asyncToPromise.js │ ├── resultToAsync.js │ └── eitherToAsync.js ├── Result │ ├── tryCatch.js │ └── eitherToResult.js ├── test │ ├── LastMonoid.js │ └── MockCrock.js ├── First │ ├── lastToFirst.js │ ├── maybeToFirst.js │ ├── eitherToFirst.js │ └── resultToFirst.js ├── Last │ ├── maybeToLast.js │ ├── firstToLast.js │ ├── eitherToLast.js │ └── resultToLast.js └── Either │ └── resultToEither.js ├── .eslintignore ├── .travis.yml ├── bin ├── publish └── setup.js ├── .gitignore ├── AUTHORS ├── webpack.config.js ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── refactor-move-task.md │ └── feature_request.md └── LICENSE /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /docs/src/CNAME: -------------------------------------------------------------------------------- 1 | crocks.dev 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | require('./src') 3 | -------------------------------------------------------------------------------- /docs/src/wedeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "hosting", 3 | "image": "wedeploy/hosting" 4 | } 5 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .deploy 3 | .publish 4 | .temp 5 | dist 6 | node_modules 7 | temp 8 | -------------------------------------------------------------------------------- /docs/src/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/evilsoft/crocks/HEAD/docs/src/images/favicon.ico -------------------------------------------------------------------------------- /docs/src/site.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Crocks", 3 | "githubRepo": "evilsoft/crocks", 4 | "googleAnalytics": "UA-37033501-5", 5 | "icon": "icon-16-loop" 6 | } 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.spec.js 2 | .npmignore 3 | test/ 4 | 5 | *.log 6 | .DS_Store 7 | .DS_Store? 8 | .Spotlight-V100 9 | .Trashes 10 | ehthumbs.db 11 | Thumbs.db 12 | docs 13 | -------------------------------------------------------------------------------- /src/core/_unit.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | Function.prototype 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | !src 4 | !docs 5 | 6 | # check js on markdown for docs 7 | docs/* 8 | !docs/src 9 | docs/src/* 10 | !docs/src/pages 11 | docs/src/pages/docs/getting-started.md -------------------------------------------------------------------------------- /src/List/index.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/List') 6 | -------------------------------------------------------------------------------- /src/Pair/index.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/Pair') 6 | -------------------------------------------------------------------------------- /src/Pred/index.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/Pred') 6 | -------------------------------------------------------------------------------- /src/Unit/index.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/Unit') 6 | -------------------------------------------------------------------------------- /src/Maybe/index.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/Maybe') 6 | -------------------------------------------------------------------------------- /src/helpers/unit.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/_unit') 6 | -------------------------------------------------------------------------------- /src/predicates/isAlt.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isAlt') 6 | -------------------------------------------------------------------------------- /src/predicates/isApply.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isApply') 6 | -------------------------------------------------------------------------------- /src/predicates/isArray.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isArray') 6 | -------------------------------------------------------------------------------- /src/predicates/isChain.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isChain') 6 | -------------------------------------------------------------------------------- /src/predicates/isEmpty.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isEmpty') 6 | -------------------------------------------------------------------------------- /src/predicates/isMap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Benny Powers (bennypowers) */ 3 | 4 | module.exports = 5 | require('../core/isMap') 6 | -------------------------------------------------------------------------------- /src/predicates/isMonad.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isMonad') 6 | -------------------------------------------------------------------------------- /src/predicates/isNil.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isNil') 6 | -------------------------------------------------------------------------------- /src/predicates/isPlus.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isPlus') 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - '12' 5 | - '10' 6 | 7 | install: 8 | - npm install 9 | 10 | script: 11 | - npm test 12 | 13 | after_success: 14 | - npm run coverage 15 | -------------------------------------------------------------------------------- /src/predicates/isDate.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | module.exports = 5 | require('../core/isDate') 6 | -------------------------------------------------------------------------------- /src/predicates/isDefined.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isDefined') 6 | -------------------------------------------------------------------------------- /src/predicates/isExtend.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isExtend') 6 | -------------------------------------------------------------------------------- /src/predicates/isFunctor.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isFunctor') 6 | -------------------------------------------------------------------------------- /src/predicates/isInteger.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isInteger') 6 | -------------------------------------------------------------------------------- /src/predicates/isMonoid.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isMonoid') 6 | -------------------------------------------------------------------------------- /src/predicates/isNumber.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isNumber') 6 | -------------------------------------------------------------------------------- /src/predicates/isObject.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isObject') 6 | -------------------------------------------------------------------------------- /src/predicates/isPromise.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isPromise') 6 | -------------------------------------------------------------------------------- /src/predicates/isString.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isString') 6 | -------------------------------------------------------------------------------- /src/predicates/isSymbol.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Robert Pearce (rpearce) */ 3 | 4 | module.exports = 5 | require('../core/isSymbol') 6 | -------------------------------------------------------------------------------- /src/predicates/isBichain.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | module.exports = 5 | require('../core/isBichain') 6 | -------------------------------------------------------------------------------- /src/predicates/isBifunctor.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isBifunctor') 6 | -------------------------------------------------------------------------------- /src/predicates/isFoldable.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isFoldable') 6 | -------------------------------------------------------------------------------- /src/predicates/isFunction.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isFunction') 6 | -------------------------------------------------------------------------------- /src/predicates/isIterable.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | module.exports = 5 | require('../core/isIterable') 6 | -------------------------------------------------------------------------------- /src/predicates/isProfunctor.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isProfunctor') 6 | -------------------------------------------------------------------------------- /src/predicates/isSameType.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isSameType') 6 | -------------------------------------------------------------------------------- /src/predicates/isSemigroup.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isSemigroup') 6 | -------------------------------------------------------------------------------- /src/predicates/isApplicative.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isApplicative') 6 | -------------------------------------------------------------------------------- /src/predicates/isSemigroupoid.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isSemigroupoid') 6 | -------------------------------------------------------------------------------- /bin/publish: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | BUILD_DIR=build 4 | 5 | mkdir -p $BUILD_DIR 6 | cd $BUILD_DIR 7 | 8 | cp ../{.npmignore,package.json,AUTHORS,LICENSE,README.md} . 9 | 10 | npm publish 11 | 12 | cd .. 13 | -------------------------------------------------------------------------------- /src/predicates/isContravariant.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = 5 | require('../core/isContravariant') 6 | -------------------------------------------------------------------------------- /src/Maybe/prop.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const getProp = require('./getProp') 5 | 6 | module.exports = 7 | getProp.origFn('prop') 8 | -------------------------------------------------------------------------------- /src/core/isMap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Benny Powers (bennypowers) */ 3 | 4 | function isMap(x) { 5 | return x instanceof Map 6 | } 7 | 8 | module.exports = isMap 9 | -------------------------------------------------------------------------------- /src/core/isArray.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | function isArray(x) { 5 | return Array.isArray(x) 6 | } 7 | 8 | module.exports = isArray 9 | -------------------------------------------------------------------------------- /src/helpers/assoc.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const setProp = require('./setProp') 5 | 6 | module.exports = 7 | setProp.origFn('assoc') 8 | -------------------------------------------------------------------------------- /src/predicates/isFunction.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | 5 | test('isFunction predicate', t => { 6 | t.equal(typeof isFunction, 'function', 'is a function') 7 | t.end() 8 | }) 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .node-version 3 | build/ 4 | 5 | .coveralls.yml 6 | .nyc_output 7 | coverage 8 | 9 | *.log 10 | 11 | .vscode 12 | .DS_Store 13 | .DS_Store? 14 | .Spotlight-V100 15 | .Trashes 16 | ehthumbs.db 17 | Thumbs.db 18 | -------------------------------------------------------------------------------- /src/Maybe/propPath.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const getPath = require('./getPath') 5 | 6 | module.exports = 7 | getPath.origFn('propPath') 8 | -------------------------------------------------------------------------------- /src/core/isDefined.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | function isDefined(x) { 5 | return x !== undefined 6 | } 7 | 8 | module.exports = isDefined 9 | -------------------------------------------------------------------------------- /src/Pair/Pair.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const Pair = require('.') 5 | 6 | test('Pair crock', t => { 7 | t.ok(isFunction(Pair), 'is a function') 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /src/core/implements.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const fulfills = 5 | algs => test => algs.indexOf(test) !== -1 6 | 7 | module.exports = fulfills 8 | -------------------------------------------------------------------------------- /src/helpers/dissoc.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const unsetProp = require('./unsetProp') 5 | 6 | module.exports = 7 | unsetProp.origFn('dissoc') 8 | -------------------------------------------------------------------------------- /src/List/List.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const List = require('.') 6 | 7 | test('List crock', t => { 8 | t.ok(isFunction(List), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/Maybe/Maybe.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const Maybe = require('.') 5 | 6 | test('Maybe crock', t => { 7 | t.ok(isFunction(Maybe), 'is a function') 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /src/Unit/Unit.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const Unit = require('.') 6 | 7 | test('Unit crock', t => { 8 | t.ok(isFunction(Unit), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/helpers/unit.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const unit = require('./unit') 6 | 7 | test('unit helper', t => { 8 | t.ok(isFunction(unit), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/helpers/propOr.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Henrique Limas */ 3 | /** @author Ian Hofmann-Hicks */ 4 | 5 | const getPropOr = require('./getPropOr') 6 | 7 | module.exports = 8 | getPropOr.origFn('propOr') 9 | -------------------------------------------------------------------------------- /src/logic/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | and: require('./and'), 3 | ifElse: require('./ifElse'), 4 | implies: require('./implies'), 5 | not: require('./not'), 6 | or: require('./or'), 7 | unless: require('./unless'), 8 | when: require('./when') 9 | } 10 | -------------------------------------------------------------------------------- /src/predicates/isAlt.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isAlt = require('./isAlt') 6 | 7 | test('isAlt predicate', t => { 8 | t.ok(isFunction(isAlt), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isMap.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isMap = require('./isMap') 6 | 7 | test('isMap predicate', t => { 8 | t.ok(isFunction(isMap), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isNil.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isNil = require('./isNil') 6 | 7 | test('isNil predicate', t => { 8 | t.ok(isFunction(isNil), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isApply.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const isApply = require('./isApply') 5 | 6 | test('isApply predicate', t => { 7 | t.ok(isFunction(isApply), 'is a function') 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /src/predicates/isFalsy.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | /** isFalsy :: a -> Boolean */ 5 | function isFalsy(x) { 6 | return !x 7 | } 8 | 9 | module.exports = isFalsy 10 | -------------------------------------------------------------------------------- /src/predicates/isPlus.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isPlus = require('./isPlus') 6 | 7 | test('isPlus predicate', t => { 8 | t.ok(isFunction(isPlus), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isSame.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | 6 | const isSame = require('../core/isSame') 7 | 8 | module.exports = curry(isSame) 9 | -------------------------------------------------------------------------------- /src/predicates/isSame.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isSame = require('./isSame') 6 | 7 | test('isSame predicate', t => { 8 | t.ok(isFunction(isSame), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/combinators/identity.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | // Identity (Idiot) 5 | /** identity :: a -> a */ 6 | const identity = 7 | x => x 8 | 9 | module.exports = identity 10 | -------------------------------------------------------------------------------- /src/helpers/propPathOr.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Henrique Limas */ 3 | /** @author Ian Hofmann-Hicks */ 4 | 5 | const getPathOr = require('./getPathOr') 6 | 7 | module.exports = 8 | getPathOr.origFn('propPathOr') 9 | -------------------------------------------------------------------------------- /src/predicates/isArray.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isArray = require('./isArray') 6 | 7 | test('isArray predicate', t => { 8 | t.ok(isFunction(isArray), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isChain.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isChain = require('./isChain') 6 | 7 | test('isChain predicate', t => { 8 | t.ok(isFunction(isChain), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isDate.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isDate = require('./isDate') 6 | 7 | test('isDate predicate', t => { 8 | t.ok(isFunction(isDate), 'is a function') 9 | 10 | t.end() 11 | }) 12 | -------------------------------------------------------------------------------- /src/predicates/isEmpty.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isEmpty = require('./isEmpty') 6 | 7 | test('isEmpty predicate', t => { 8 | t.ok(isFunction(isEmpty), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isMonad.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isMonad = require('./isMonad') 6 | 7 | test('isMonad predicate', t => { 8 | t.ok(isFunction(isMonad), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isTrue.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | /** isTrue :: a -> Boolean */ 5 | function isTrue(x) { 6 | return x === true 7 | } 8 | 9 | module.exports = isTrue 10 | -------------------------------------------------------------------------------- /src/predicates/isTruthy.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | /** isTruthy :: a -> Boolean */ 5 | function isTruthy(x) { 6 | return !!x 7 | } 8 | 9 | module.exports = isTruthy 10 | -------------------------------------------------------------------------------- /src/core/isString.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | /** isString :: a -> Boolean */ 5 | function isString(x) { 6 | return typeof x === 'string' 7 | } 8 | 9 | module.exports = isString 10 | -------------------------------------------------------------------------------- /src/core/isSymbol.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Robert Pearce (rpearce) */ 3 | 4 | /** isSymbol :: a -> Boolean */ 5 | function isSymbol(x) { 6 | return typeof x === 'symbol' 7 | } 8 | 9 | module.exports = isSymbol 10 | -------------------------------------------------------------------------------- /src/predicates/isExtend.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isExtend = require('./isExtend') 6 | 7 | test('isExtend predicate', t => { 8 | t.ok(isFunction(isExtend), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isFalse.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | /** isFalse :: a -> Boolean */ 5 | function isFalse(x) { 6 | return x === false 7 | } 8 | 9 | module.exports = isFalse 10 | -------------------------------------------------------------------------------- /src/predicates/isInteger.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const isInteger = require('../core/isNil') 5 | 6 | test('isInteger predicate', t => { 7 | t.ok(isFunction(isInteger), 'is a function') 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /src/predicates/isMonoid.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isMonoid = require('./isMonoid') 6 | 7 | test('isMonoid predicate', t => { 8 | t.ok(isFunction(isMonoid), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isNumber.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isNumber = require('./isNumber') 6 | 7 | test('isNumber predicate', t => { 8 | t.ok(isFunction(isNumber), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isObject.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isObject = require('./isObject') 6 | 7 | test('isObject predicate', t => { 8 | t.ok(isFunction(isObject), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isString.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isString = require('./isString') 6 | 7 | test('isString predicate', t => { 8 | t.ok(isFunction(isString), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isSymbol.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isSymbol = require('./isSymbol') 6 | 7 | test('isSymbol predicate', t => { 8 | t.ok(isFunction(isSymbol), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/propPathSatisfies.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evilsoft) */ 3 | 4 | const pathSatisfies = require('./pathSatisfies') 5 | 6 | module.exports = 7 | pathSatisfies.origFn('propPathSatisfies') 8 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Ian Hofmann-Hicks (https://github.com/evilsoft) 2 | Ryan Stegmann (https://github.com/rstegg) 3 | Andrew Van Slaars (https://github.com/avanslaars) 4 | Henrique Limas (https://github.com/HenriqueLimas) 5 | Robert Pearce (http://robertwpearce.com/) 6 | -------------------------------------------------------------------------------- /docs/src/partials/TutorialTimer.soy: -------------------------------------------------------------------------------- 1 | {namespace TutorialTimer} 2 | 3 | /** 4 | * @param? time 5 | */ 6 | {template .render} 7 |

8 | {if $time} 9 | {$time} 10 | {/if} 11 |

12 | {/template} 13 | -------------------------------------------------------------------------------- /src/predicates/isBichain.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isBichain = require('./isBichain') 6 | 7 | test('isBichain predicate', t => { 8 | t.ok(isFunction(isBichain), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isDefined.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isDefined = require('./isDefined') 6 | 7 | test('isDefined predicate', t => { 8 | t.ok(isFunction(isDefined), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isFunctor.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isFunctor = require('./isFunctor') 6 | 7 | test('isFunctor predicate', t => { 8 | t.ok(isFunction(isFunctor), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isPromise.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isPromise = require('./isPromise') 6 | 7 | test('isPromise predicate', t => { 8 | t.ok(isFunction(isPromise), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/propPathEq.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Karthik Iyengar (karthikiyengar) */ 3 | /** @author Ian Hofmann-Hicks */ 4 | 5 | const pathEq = require('./pathEq') 6 | 7 | module.exports = 8 | pathEq.origFn('propPathEq') 9 | -------------------------------------------------------------------------------- /src/predicates/isFoldable.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isFoldable = require('./isFoldable') 6 | 7 | test('isFoldable predicate', t => { 8 | t.ok(isFunction(isFoldable), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isSameType.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isSameType = require('./isSameType') 6 | 7 | test('isSameType predicate', t => { 8 | t.ok(isFunction(isSameType), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/core/isFunction.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | /** isFunction :: a -> Boolean */ 5 | function isFunction(fn) { 6 | return typeof fn === 'function' 7 | } 8 | 9 | module.exports = isFunction 10 | -------------------------------------------------------------------------------- /src/predicates/isBifunctor.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isBifunctor = require('./isBifunctor') 6 | 7 | test('isBifunctor predicate', t => { 8 | t.ok(isFunction(isBifunctor), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isBoolean.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | /** isBoolean :: a -> Boolean */ 5 | function isBoolean(x) { 6 | return typeof x === 'boolean' 7 | } 8 | 9 | module.exports = isBoolean 10 | -------------------------------------------------------------------------------- /src/predicates/isSemigroup.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isSemigroup = require('./isSemigroup') 6 | 7 | test('isSemigroup predicate', t => { 8 | t.ok(isFunction(isSemigroup), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isApplicative.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const isApplicative = require('./isApplicative') 5 | 6 | test('isApplicative predicate', t => { 7 | t.ok(isFunction(isApplicative), 'is a function') 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | 3 | module.exports = { 4 | mode: 'none', 5 | entry: './build/index.js', 6 | output: { 7 | filename: 'crocks.js', 8 | path: path.resolve(__dirname, 'build', 'dist'), 9 | library: 'crocks', 10 | libraryTarget: 'umd' 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/core/isNil.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | /* eslint eqeqeq: "off" */ 5 | 6 | /** isNil :: a -> Boolean */ 7 | function isNil(x) { 8 | return x == null || x !== x 9 | } 10 | 11 | module.exports = isNil 12 | -------------------------------------------------------------------------------- /src/core/isNumber.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | /** isNumber :: a -> Boolean */ 5 | function isNumber(x) { 6 | return typeof x === 'number' 7 | && !isNaN(x) 8 | } 9 | 10 | module.exports = isNumber 11 | -------------------------------------------------------------------------------- /src/Pair/branch.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Pair = require('../core/Pair') 5 | 6 | /** branch :: a -> Pair a a */ 7 | function branch(x) { 8 | return Pair(x, x) 9 | } 10 | 11 | module.exports = branch 12 | -------------------------------------------------------------------------------- /src/predicates/isContravariant.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const isContravariant = require('./isContravariant') 5 | 6 | test('isContravariant predicate', t => { 7 | t.ok(isFunction(isContravariant), 'is a function') 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /src/predicates/isProfunctor.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isProfunctor = require('./isProfunctor') 6 | 7 | test('isProfunctor predicate function', t => { 8 | t.ok(isFunction(isProfunctor), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/predicates/isSemigroupoid.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | 5 | const isSemigroupoid = require('./isSemigroupoid') 6 | 7 | test('isSemigroupoid predicate', t => { 8 | t.ok(isFunction(isSemigroupoid), 'is a function') 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /src/core/isBichain.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | 6 | /** isBichain :: a -> Boolean */ 7 | function isBichain(m) { 8 | return hasAlg('bichain', m) 9 | } 10 | 11 | module.exports = isBichain 12 | -------------------------------------------------------------------------------- /src/core/isFunctor.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | 6 | /** isFunctor :: a -> Boolean */ 7 | function isFunctor(m) { 8 | return !!m && hasAlg('map', m) 9 | } 10 | 11 | module.exports = isFunctor 12 | -------------------------------------------------------------------------------- /src/core/isTypeRepOf.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('./isFunction') 5 | 6 | const isTypeRepOf = (x, y) => 7 | isFunction(y) 8 | && (x === y || x.name === y.name) 9 | 10 | module.exports = isTypeRepOf 11 | -------------------------------------------------------------------------------- /src/pointfree/valueOf.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isNil = require('../core/isNil') 5 | 6 | function valueOf(m) { 7 | if(isNil(m)) { 8 | return m 9 | } 10 | 11 | return m.valueOf() 12 | } 13 | 14 | module.exports = valueOf 15 | -------------------------------------------------------------------------------- /src/combinators/constant.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | 6 | // Constant (Kestrel) 7 | /** constant :: a -> b -> a */ 8 | const constant = 9 | x => () => x 10 | 11 | module.exports = curry(constant) 12 | -------------------------------------------------------------------------------- /src/core/isDate.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | /** isDate :: a -> Boolean */ 5 | function isDate(x) { 6 | return Object.prototype.toString.apply(x) === '[object Date]' 7 | && !isNaN(x.valueOf()) 8 | } 9 | 10 | module.exports = isDate 11 | 12 | -------------------------------------------------------------------------------- /src/core/isFoldable.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | 6 | /** isFoldable :: a -> Boolean */ 7 | function isFoldable(m) { 8 | return !!m 9 | && hasAlg('reduce', m) 10 | } 11 | 12 | module.exports = isFoldable 13 | -------------------------------------------------------------------------------- /src/pointfree/equals.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const _equals = require('../core/equals') 5 | const curry = require('../core/curry') 6 | 7 | function equals(x, y) { 8 | return _equals(x, y) 9 | } 10 | 11 | module.exports = 12 | curry(equals) 13 | -------------------------------------------------------------------------------- /src/Pred/Pred.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const index = require('.') 5 | const Pred = require('../core/Pred') 6 | 7 | test('Pred crock', t => { 8 | t.ok(isFunction(index), 'is a function') 9 | 10 | t.equals(Pred, index, 'provides the expected Pred') 11 | 12 | t.end() 13 | }) 14 | -------------------------------------------------------------------------------- /src/core/compose.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | // Composition (Bluebird) 5 | /** compose :: (b -> c) -> (a -> b) -> a -> c */ 6 | function compose(f, g) { 7 | return function(x) { 8 | return f(g(x)) 9 | } 10 | } 11 | 12 | module.exports = compose 13 | -------------------------------------------------------------------------------- /src/core/isSame.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | /** isSame :: (a, b) -> Boolean */ 5 | function isSame(x, y) { 6 | if(x === y) { 7 | return x !== 0 || 1 / x === 1 / y 8 | } 9 | 10 | return x !== x && y !== y 11 | } 12 | 13 | module.exports = isSame 14 | -------------------------------------------------------------------------------- /src/core/isSemigroupoid.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | 6 | /** isSemigroupoid :: a -> Boolean */ 7 | function isSemigroupoid(m) { 8 | return !!m && hasAlg('compose', m) 9 | } 10 | 11 | module.exports = isSemigroupoid 12 | -------------------------------------------------------------------------------- /src/predicates/isSetoid.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('../core/hasAlg') 5 | 6 | /** isSetoid :: a -> Boolean */ 7 | function isSetoid(m) { 8 | return !!m 9 | && hasAlg('equals', m) 10 | } 11 | 12 | module.exports = isSetoid 13 | 14 | -------------------------------------------------------------------------------- /src/core/isContravariant.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | 6 | /** isContravariant :: a -> Boolean */ 7 | function isContravariant(m) { 8 | return !!m && hasAlg('contramap', m) 9 | } 10 | 11 | module.exports = isContravariant 12 | -------------------------------------------------------------------------------- /src/core/isObject.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const toString = Object.prototype.toString 5 | 6 | /** isObject :: a -> Boolean */ 7 | function isObject(x) { 8 | return !!x 9 | && toString.call(x) === '[object Object]' 10 | } 11 | 12 | module.exports = isObject 13 | -------------------------------------------------------------------------------- /src/core/predOrFunc.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('./isFunction') 5 | 6 | function predOrFunc(pred, x) { 7 | if(isFunction(pred)) { 8 | return pred(x) 9 | } 10 | return pred.runWith(x) 11 | } 12 | 13 | module.exports = predOrFunc 14 | -------------------------------------------------------------------------------- /src/combinators/identity.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const identity = require('./identity') 4 | const isFunction = require('../core/isFunction') 5 | 6 | test('identity (I combinator)', t => { 7 | const x = 'somehting' 8 | 9 | t.ok(isFunction(identity), 'is a function') 10 | t.equal(identity(x), x, 'returns the passed argument') 11 | 12 | t.end() 13 | }) 14 | -------------------------------------------------------------------------------- /src/core/isAlt.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isFunctor = require('./isFunctor') 6 | 7 | /** isAlt :: a -> Boolean */ 8 | function isAlt(m) { 9 | return isFunctor(m) 10 | && hasAlg('alt', m) 11 | } 12 | 13 | module.exports = isAlt 14 | -------------------------------------------------------------------------------- /src/core/isInteger.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isNumber = require('./isNumber') 5 | 6 | /** isInteger :: a -> Boolean */ 7 | function isInteger(x) { 8 | return isNumber(x) 9 | && isFinite(x) 10 | && Math.floor(x) === x 11 | } 12 | 13 | module.exports = isInteger 14 | -------------------------------------------------------------------------------- /src/Writer/log.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | 6 | function log(m) { 7 | if(!(m && isFunction(m.log))) { 8 | throw new TypeError('log: Writer required') 9 | } 10 | 11 | return m.log() 12 | } 13 | 14 | module.exports = log 15 | -------------------------------------------------------------------------------- /src/combinators/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | applyTo: require('./applyTo'), 3 | compose2: require('./compose2'), 4 | composeB: require('./composeB'), 5 | constant: require('./constant'), 6 | converge: require('./converge'), 7 | flip: require('./flip'), 8 | identity: require('./identity'), 9 | psi: require('./psi'), 10 | substitution: require('./substitution') 11 | } 12 | -------------------------------------------------------------------------------- /src/core/isChain.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isApply = require('./isApply') 6 | 7 | /** isChain :: a -> Boolean */ 8 | function isChain(m) { 9 | return isApply(m) 10 | && hasAlg('chain', m) 11 | } 12 | 13 | module.exports = isChain 14 | -------------------------------------------------------------------------------- /src/core/isPromise.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('./isFunction') 5 | 6 | /** isPromise :: a -> Boolean */ 7 | function isPromise(p) { 8 | return !!p 9 | && isFunction(p.then) 10 | && isFunction(p.catch) 11 | } 12 | 13 | module.exports = isPromise 14 | -------------------------------------------------------------------------------- /src/pointfree/run.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | 6 | function run(m) { 7 | if(!(m && isFunction(m.run))) { 8 | throw new TypeError('run: IO required') 9 | } 10 | 11 | return m.run() 12 | } 13 | 14 | module.exports = run 15 | -------------------------------------------------------------------------------- /src/Pair/fst.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | 6 | function fst(m) { 7 | if(!(m && isFunction(m.fst))) { 8 | throw new TypeError('fst: Argument must be a Pair') 9 | } 10 | 11 | return m.fst() 12 | } 13 | 14 | module.exports = fst 15 | -------------------------------------------------------------------------------- /src/Pair/snd.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | 6 | function snd(m) { 7 | if(!(m && isFunction(m.snd))) { 8 | throw new TypeError('snd: Argument must be a Pair') 9 | } 10 | 11 | return m.snd() 12 | } 13 | 14 | module.exports = snd 15 | -------------------------------------------------------------------------------- /src/core/isApply.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isFunctor = require('./isFunctor') 6 | 7 | /** isApply :: a -> Boolean */ 8 | function isApply(m) { 9 | return isFunctor(m) 10 | && hasAlg('ap', m) 11 | } 12 | 13 | module.exports = isApply 14 | -------------------------------------------------------------------------------- /src/core/isIterable.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | const isFunction = require('./isFunction') 5 | const isNil = require('./isNil') 6 | 7 | function isIterable(iterable) { 8 | return !isNil(iterable) && isFunction(iterable[Symbol.iterator]) 9 | } 10 | 11 | module.exports = isIterable 12 | -------------------------------------------------------------------------------- /src/Writer/read.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | 6 | function read(m) { 7 | if(!(m && isFunction(m.read))) { 8 | throw new TypeError('read: Writer required') 9 | } 10 | 11 | return m.read() 12 | } 13 | 14 | module.exports = read 15 | 16 | -------------------------------------------------------------------------------- /src/core/isExtend.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isFunctor = require('./isFunctor') 6 | 7 | /** isExtend :: a -> Boolean */ 8 | function isExtend(m) { 9 | return isFunctor(m) 10 | && hasAlg('extend', m) 11 | } 12 | 13 | module.exports = isExtend 14 | -------------------------------------------------------------------------------- /src/core/type.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('./isFunction') 5 | 6 | function type(x) { 7 | if(x) { 8 | if(isFunction(x.type)) { 9 | return x.type() 10 | } 11 | } 12 | return {}.toString.call(x).slice(8, -1) 13 | } 14 | 15 | module.exports = type 16 | -------------------------------------------------------------------------------- /src/helpers/defaultTo.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isNil = require('../core/isNil') 6 | 7 | /** defaultTo :: a -> b -> (a | b) */ 8 | function defaultTo(def, val) { 9 | return isNil(val) ? def : val 10 | } 11 | 12 | module.exports = curry(defaultTo) 13 | -------------------------------------------------------------------------------- /docs/src/partials/SocialButtons.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Component from 'metal-component'; 4 | import Soy from 'metal-soy'; 5 | 6 | import templates from './SocialButtons.soy'; 7 | 8 | class SocialButtons extends Component { 9 | rendered() { 10 | this.siteUrl = window.location.origin; 11 | } 12 | }; 13 | 14 | Soy.register(SocialButtons, templates); 15 | 16 | export default SocialButtons; 17 | -------------------------------------------------------------------------------- /src/core/apOrFunc.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isApplicative = require('./isApplicative') 5 | const isTypeRepOf = require('./isTypeRepOf') 6 | 7 | const apOrFunc = af => x => 8 | isApplicative(af) 9 | ? af.of(x) 10 | : isTypeRepOf(Array, af) ? [ x ] : af(x) 11 | 12 | module.exports = apOrFunc 13 | -------------------------------------------------------------------------------- /src/core/isBifunctor.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isFunctor = require('./isFunctor') 6 | 7 | /** isBifunctor :: a -> Boolean */ 8 | function isBifunctor(m) { 9 | return isFunctor(m) 10 | && hasAlg('bimap', m) 11 | } 12 | 13 | module.exports = isBifunctor 14 | -------------------------------------------------------------------------------- /src/core/isMonad.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isApplicative = require('./isApplicative') 6 | 7 | /** isMonad :: a -> Boolean */ 8 | function isMonad(m) { 9 | return isApplicative(m) 10 | && hasAlg('chain', m) 11 | } 12 | 13 | module.exports = isMonad 14 | 15 | -------------------------------------------------------------------------------- /src/core/isPlus.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isAlt = require('./isAlt') 6 | 7 | /** isPlus :: a -> Boolean */ 8 | function isPlus(m) { 9 | return isAlt(m) 10 | && (hasAlg('zero', m) || hasAlg('zero', m.constructor)) 11 | } 12 | 13 | module.exports = isPlus 14 | -------------------------------------------------------------------------------- /src/core/isSemigroup.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isString = require('./isString') 5 | const hasAlg = require('./hasAlg') 6 | 7 | /** isSemigroup :: a -> Boolean */ 8 | function isSemigroup(m) { 9 | return isString(m) 10 | || !!m && hasAlg('concat', m) 11 | } 12 | 13 | module.exports = isSemigroup 14 | -------------------------------------------------------------------------------- /src/predicates/isAlternative.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isApplicative = require('../core/isApplicative') 5 | const isPlus = require('../core/isPlus') 6 | 7 | /** isAlternative :: a -> Boolean */ 8 | function isAlternative(m) { 9 | return isPlus(m) 10 | && isApplicative(m) 11 | } 12 | 13 | module.exports = isAlternative 14 | -------------------------------------------------------------------------------- /src/predicates/isIterable.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const coreIsIterable = require('../core/isIterable') 5 | 6 | const isIterable = require('./isIterable') 7 | 8 | test('isIterable predicate', t => { 9 | t.ok(isFunction(isIterable), 'is a function') 10 | t.equal(isIterable, coreIsIterable, 'is exposing the expected function') 11 | 12 | t.end() 13 | }) 14 | -------------------------------------------------------------------------------- /src/predicates/isTraversable.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('../core/hasAlg') 5 | const isFunctor = require('../core/isFunctor') 6 | 7 | /** isTraversable :: a -> Boolean */ 8 | function isTraversable(m) { 9 | return isFunctor(m) 10 | && hasAlg('traverse', m) 11 | } 12 | 13 | module.exports = isTraversable 14 | -------------------------------------------------------------------------------- /src/core/isApplicative.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isApply = require('./isApply') 6 | 7 | /** isApplicative :: a -> Boolean */ 8 | function isApplicative(m) { 9 | return isApply(m) 10 | && (hasAlg('of', m) || hasAlg('of', m.constructor)) 11 | } 12 | 13 | module.exports = isApplicative 14 | -------------------------------------------------------------------------------- /src/core/isMonoid.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isSemigroup = require('./isSemigroup') 6 | 7 | /** isMonoid :: a -> Boolean */ 8 | function isMonoid(m) { 9 | return isSemigroup(m) 10 | && (hasAlg('empty', m) || hasAlg('empty', m.constructor)) 11 | } 12 | 13 | module.exports = isMonoid 14 | -------------------------------------------------------------------------------- /src/core/once.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | /** once :: ((*) -> b) -> ((*) -> b) */ 5 | function once(fn) { 6 | var called, result 7 | 8 | return function() { 9 | if(!called) { 10 | called = true 11 | result = fn.apply(null, arguments) 12 | } 13 | 14 | return result 15 | } 16 | } 17 | 18 | module.exports = once 19 | -------------------------------------------------------------------------------- /src/predicates/isCategory.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('../core/hasAlg') 5 | const isSemigroupoid = require('../core/isSemigroupoid') 6 | 7 | /** isCategory :: a -> Boolean */ 8 | function isCategory(m) { 9 | return isSemigroupoid(m) 10 | && (hasAlg('id', m) || hasAlg('id', m.constructor)) 11 | } 12 | 13 | module.exports = isCategory 14 | -------------------------------------------------------------------------------- /src/core/mconcatMap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const compose = require('./compose') 5 | 6 | const foldWith = 7 | m => (x, y) => x.concat(m(y)) 8 | 9 | /** mconcatMap :: Monoid M => M -> (b -> a) -> ([ b ] | List b) -> M a */ 10 | function mconcatMap(M, f, xs) { 11 | return xs.reduce(foldWith(compose(M, f)), M.empty()) 12 | } 13 | 14 | module.exports = mconcatMap 15 | -------------------------------------------------------------------------------- /src/helpers/unary.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | 6 | /** unary :: (* -> b) -> a -> b */ 7 | function unary(fn) { 8 | if(!isFunction(fn)) { 9 | throw new TypeError('unary: Argument must be a Function') 10 | } 11 | 12 | return function(x) { 13 | return fn(x) 14 | } 15 | } 16 | 17 | module.exports = unary 18 | -------------------------------------------------------------------------------- /docs/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | $accent: #FFCC00; 2 | 3 | @import "marble"; 4 | 5 | // Root 6 | @import "templates/root"; 7 | 8 | // Landing 9 | @import "templates/landing"; 10 | 11 | // Docs 12 | @import "templates/docs"; 13 | 14 | // Search 15 | @import "templates/search"; 16 | 17 | // Updates 18 | @import "templates/updates"; 19 | 20 | // Blog 21 | @import "templates/blog"; 22 | 23 | // Tutorial 24 | @import "templates/tutorial"; 25 | 26 | @import "custom/landing"; 27 | 28 | -------------------------------------------------------------------------------- /src/Tuple/project.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Karthik Iyengar (karthikiyengar) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | const curry = require('../core/curry') 6 | 7 | function project(index, m) { 8 | if(!(m && isFunction(m.project))) { 9 | throw new TypeError('project: Tuple required') 10 | } 11 | 12 | return m.project(index) 13 | } 14 | 15 | module.exports = curry(project) 16 | -------------------------------------------------------------------------------- /src/helpers/once.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | const _once = require('../core/once') 6 | 7 | /** once :: ((*) -> b) -> ((*) -> b) */ 8 | function once(fn) { 9 | if(!isFunction(fn)) { 10 | throw new TypeError('once: Argument must be a Function') 11 | } 12 | 13 | return _once(fn) 14 | } 15 | 16 | module.exports = once 17 | -------------------------------------------------------------------------------- /src/State/evalWith.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function evalWith(x, m) { 8 | if(!(m && isFunction(m.evalWith))) { 9 | throw new TypeError('evalWith: State required for second argument') 10 | } 11 | 12 | return m.evalWith(x) 13 | } 14 | 15 | module.exports = curry(evalWith) 16 | -------------------------------------------------------------------------------- /src/State/execWith.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function execWith(x, m) { 8 | if(!(m && isFunction(m.execWith))) { 9 | throw new TypeError('execWith: State required for second argument') 10 | } 11 | 12 | return m.execWith(x) 13 | } 14 | 15 | module.exports = curry(execWith) 16 | -------------------------------------------------------------------------------- /src/core/implements.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | 5 | const _implements = require('./implements') 6 | 7 | test('implements', t => { 8 | t.ok(isFunction(_implements), 'is a function') 9 | 10 | const f = _implements([ 'bob' ]) 11 | 12 | t.equal(f('bob'), true, 'returns true when value is in initial array') 13 | t.equal(f('joey'), false,'returns false when value is not in initial array') 14 | 15 | t.end() 16 | }) 17 | -------------------------------------------------------------------------------- /src/pointfree/option.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function option(x, m) { 8 | if(!(m && isFunction(m.option))) { 9 | throw new TypeError('option: Last argument must be a Maybe, First or Last') 10 | } 11 | 12 | return m.option(x) 13 | } 14 | 15 | module.exports = curry(option) 16 | -------------------------------------------------------------------------------- /src/core/isPredOrFunc.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | const Pred = require('./types').proxy('Pred') 5 | 6 | const isFunction = require('./isFunction') 7 | const isSameType = require('./isSameType') 8 | 9 | /** isPredOrFunc :: ((a -> b) | pred) -> bool */ 10 | const isPredOrFunc = predOrFunc => 11 | isFunction(predOrFunc) || isSameType(Pred, predOrFunc) 12 | 13 | module.exports = isPredOrFunc 14 | -------------------------------------------------------------------------------- /src/core/isProfunctor.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('./hasAlg') 5 | const isContravariant = require('./isContravariant') 6 | const isFunctor = require('./isFunctor') 7 | 8 | /** isProfunctor :: a -> Boolean */ 9 | function isProfunctor(m) { 10 | return isContravariant(m) 11 | && isFunctor(m) 12 | && hasAlg('promap', m) 13 | } 14 | 15 | module.exports = isProfunctor 16 | -------------------------------------------------------------------------------- /src/helpers/binary.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curryN = require('../core/curryN') 5 | const isFunction = require('../core/isFunction') 6 | 7 | /** binary :: (* -> c) -> a -> b -> c */ 8 | function binary(fn) { 9 | if(!isFunction(fn)) { 10 | throw new TypeError('binary: Argument must be a Function') 11 | } 12 | 13 | return curryN(2, fn) 14 | } 15 | 16 | module.exports = binary 17 | -------------------------------------------------------------------------------- /src/helpers/curry.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const _curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | /** curry :: ((a, b, c) -> d) -> a -> b -> c -> d */ 8 | function curry(fn) { 9 | if(!isFunction(fn)) { 10 | throw new TypeError('curry: Argument must be a Function') 11 | } 12 | 13 | return _curry(fn) 14 | } 15 | 16 | module.exports = curry 17 | -------------------------------------------------------------------------------- /src/core/cloneIterable.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Henrique Limas (HenriqueLimas) */ 3 | 4 | function cloneIterable(source) { 5 | let copy = Object.create(Object.getPrototypeOf(source)) 6 | Object.assign(copy, source) 7 | 8 | const symbols = Object.getOwnPropertySymbols(source) 9 | symbols.forEach(symbol => { 10 | copy[symbol] = source[symbol] 11 | }) 12 | 13 | return copy 14 | } 15 | 16 | module.exports = cloneIterable 17 | -------------------------------------------------------------------------------- /src/pointfree/compareWith.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function compareWith(x, y, m) { 8 | if(!(m && isFunction(m.compareWith))) { 9 | throw new TypeError('compareWith: Equiv required for third argument') 10 | } 11 | 12 | return m.compareWith(x, y) 13 | } 14 | 15 | module.exports = curry(compareWith) 16 | -------------------------------------------------------------------------------- /src/pointfree/runWith.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function runWith(x, m) { 8 | if(!(m && isFunction(m.runWith))) { 9 | throw new TypeError('runWith: Arrow, Endo, Pred, Reader, Star or State required for second argument') 10 | } 11 | 12 | return m.runWith(x) 13 | } 14 | 15 | module.exports = curry(runWith) 16 | -------------------------------------------------------------------------------- /src/helpers/objOf.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isString = require('../core/isString') 6 | 7 | /** objOf :: String -> a -> Object */ 8 | function objOf(key, value) { 9 | if(!(key && isString(key))) { 10 | throw new TypeError('objOf: Non-empty String required for first argument') 11 | } 12 | 13 | return { [key]: value } 14 | } 15 | 16 | module.exports = curry(objOf) 17 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "crocks-docs", 4 | "version": "0.0.0", 5 | "scripts": { 6 | "start": "electric run --env dev", 7 | "docs:build": "electric build", 8 | "docs:deploy": "electric deploy" 9 | }, 10 | "devDependencies": { 11 | "electric-cli": "^2.4.2", 12 | "electric-marble-components": "^3.0.0", 13 | "marble": "~3.1.3", 14 | "marble-topbar": "^1.0.0", 15 | "markdown-slug": "^0.1.1", 16 | "moment": "^2.19.2", 17 | "rimraf": "^2.6.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/combinators/applyTo.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | // Application (Thrush) 8 | /** applyTo :: a -> (a -> b) -> b */ 9 | function applyTo(x, f) { 10 | if(!isFunction(f)) { 11 | throw new TypeError('applyTo: Function required for second argument') 12 | } 13 | 14 | return f(x) 15 | } 16 | 17 | module.exports = curry(applyTo) 18 | -------------------------------------------------------------------------------- /src/core/hasAlg.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('./isFunction') 5 | const fl = require('./flNames') 6 | 7 | const check = (alg, m) => 8 | isFunction(m[fl[alg]]) || isFunction(m[alg]) 9 | 10 | const checkImpl = (alg, m) => 11 | isFunction(m['@@implements']) && !!m['@@implements'](alg) 12 | 13 | const hasAlg = (alg, m) => 14 | !!m && (check(alg, m) || checkImpl(alg, m)) 15 | 16 | module.exports = hasAlg 17 | -------------------------------------------------------------------------------- /src/core/curryN.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | function curryN(n, fn) { 5 | return function(...xs) { 6 | const args = 7 | xs.length ? xs : [ undefined ] 8 | 9 | const remaining = 10 | Math.floor(n) - args.length 11 | 12 | return remaining > 0 13 | ? curryN(remaining, Function.bind.apply(fn, [ null ].concat(args))) 14 | : fn.apply(null, args.slice(0, n)) 15 | } 16 | } 17 | 18 | module.exports = curryN 19 | -------------------------------------------------------------------------------- /src/Async/race.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isSameType = require('../core/isSameType') 6 | 7 | const Async = require('../core/types').proxy('Async') 8 | 9 | function race(m, a) { 10 | if(!(isSameType(m, a) && isSameType(Async, m))) { 11 | throw new TypeError('race: Both arguments must be Asyncs') 12 | } 13 | 14 | return a.race(m) 15 | } 16 | 17 | module.exports = 18 | curry(race) 19 | -------------------------------------------------------------------------------- /src/combinators/flip.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | // Flip (Cardinal) 8 | // flip :: (a -> b -> c) -> b -> a -> c 9 | function flip(f, x, y) { 10 | if(!isFunction(f)) { 11 | throw new TypeError( 12 | 'flip: Function required for first argument' 13 | ) 14 | } 15 | 16 | return curry(f)(y, x) 17 | } 18 | 19 | module.exports = curry(flip) 20 | -------------------------------------------------------------------------------- /docs/src/partials/Sidebar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Component from 'metal-component'; 4 | import Soy from 'metal-soy'; 5 | import Toggler from 'metal-toggler'; 6 | 7 | import templates from './Sidebar.soy'; 8 | 9 | class Sidebar extends Component { 10 | attached() { 11 | this._toggler = new Toggler({ 12 | content: '.sidebar-toggler-content', 13 | header: '.sidebar-header' 14 | }); 15 | } 16 | 17 | disposed() { 18 | this._toggler.dispose(); 19 | } 20 | }; 21 | 22 | Soy.register(Sidebar, templates); 23 | 24 | export default Sidebar; 25 | -------------------------------------------------------------------------------- /src/combinators/psi.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | // PSI (P) 8 | /** psi :: (b -> b -> c) -> (a -> b) -> a -> a -> c */ 9 | function psi(f, g, x, y) { 10 | if(!isFunction(f) || !isFunction(g)) { 11 | throw new TypeError('psi: First and second arguments must be functions') 12 | } 13 | 14 | return curry(f)(g(x), g(y)) 15 | } 16 | 17 | module.exports = curry(psi) 18 | -------------------------------------------------------------------------------- /src/core/isSameType.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('./curry') 5 | const isFunction = require('./isFunction') 6 | const type = require('./type') 7 | 8 | /** isSameType :: Container m => (m, m) -> Boolean */ 9 | function isSameType(x, y) { 10 | const tX = type(x) 11 | const tY = type(y) 12 | 13 | return tX === tY 14 | || isFunction(x) && x.name === tY 15 | || isFunction(y) && y.name === tX 16 | } 17 | 18 | module.exports = curry(isSameType) 19 | -------------------------------------------------------------------------------- /src/helpers/assign.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isObject = require('../core/isObject') 6 | const object = require('../core/object') 7 | 8 | /** assign :: Object -> Object -> Object */ 9 | function assign(x, m) { 10 | if(!(isObject(x) && isObject(m))) { 11 | throw new TypeError('assign: Objects required for both arguments') 12 | } 13 | 14 | return object.assign(x, m) 15 | } 16 | 17 | module.exports = curry(assign) 18 | -------------------------------------------------------------------------------- /src/pointfree/cons.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isArray = require('../core/isArray') 6 | const isFunction = require('../core/isFunction') 7 | 8 | function cons(x, m) { 9 | if(m && isFunction(m.cons)) { 10 | return m.cons(x) 11 | } 12 | else if(isArray(m)) { 13 | return [ x ].concat(m) 14 | } 15 | 16 | throw new TypeError('cons: List or Array required for second argument') 17 | } 18 | 19 | module.exports = curry(cons) 20 | -------------------------------------------------------------------------------- /src/core/once.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | const sinon = require('sinon') 3 | 4 | const isFunction = require('./isFunction') 5 | 6 | const identity = x => x 7 | 8 | const once = require('./once') 9 | 10 | test('once core', t => { 11 | t.ok(isFunction(once), 'is a function') 12 | 13 | const inner = sinon.spy(identity) 14 | const fn = once(inner) 15 | const x = 'smiles' 16 | 17 | t.equals(fn(x), x, 'returns first value') 18 | t.equals(fn('another'), x, 'caches original value') 19 | t.ok(inner.calledOnce, 'only calls wrapped function once') 20 | 21 | t.end() 22 | }) 23 | -------------------------------------------------------------------------------- /docs/src/layouts/main.soy: -------------------------------------------------------------------------------- 1 | {namespace main} 2 | 3 | /** 4 | * @param content 5 | * @param site 6 | * @param? elementClasses 7 | */ 8 | {template .render} 9 |
10 |
11 | {call Topbar.render} 12 | {param items: $site.topbar /} 13 | {param style: 'topbar-light' /} 14 | {param logo: [ 15 | 'text': $site.title, 16 | 'icon': $site.icon, 17 | 'href': $site.basePath 18 | ] /} 19 | {/call} 20 | 21 | {$content} 22 |
23 |
24 | {/template} 25 | -------------------------------------------------------------------------------- /src/pointfree/merge.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function merge(fn, m) { 8 | if(!isFunction(fn)) { 9 | throw new TypeError('merge: Function required for first argument') 10 | } 11 | 12 | if(!(m && isFunction(m.merge))) { 13 | throw new TypeError('merge: Pair or Tuple required for second argument') 14 | } 15 | 16 | return m.merge(fn) 17 | } 18 | 19 | module.exports = curry(merge) 20 | -------------------------------------------------------------------------------- /src/helpers/defaultProps.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isObject = require('../core/isObject') 6 | const object = require('../core/object') 7 | 8 | /** defaultProps :: Object -> Object -> Object */ 9 | function defaultProps(x, m) { 10 | if(!isObject(x) || !isObject(m)) { 11 | throw new TypeError('defaultProps: Objects required for both arguments') 12 | } 13 | 14 | return object.assign(m, x) 15 | } 16 | 17 | module.exports = curry(defaultProps) 18 | -------------------------------------------------------------------------------- /src/helpers/tap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const compose = require('../core/compose') 6 | const isFunction = require('../core/isFunction') 7 | 8 | const constant = x => () => x 9 | 10 | /** tap :: (a -> b) -> a -> a */ 11 | function tap(fn, x) { 12 | if(!isFunction(fn)) { 13 | throw new TypeError( 14 | 'tap: Function required for first argument' 15 | ) 16 | } 17 | 18 | return compose(constant(x), fn)(x) 19 | } 20 | 21 | module.exports = curry(tap) 22 | -------------------------------------------------------------------------------- /src/logic/not.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isPredOrFunc = require('../core/isPredOrFunc') 6 | const predOrFunc = require('../core/predOrFunc') 7 | 8 | /** not :: (a -> Boolean) | Pred -> a -> Boolean */ 9 | function not(pred, x) { 10 | if(!isPredOrFunc(pred)) { 11 | throw new TypeError( 12 | 'not: Pred or predicate function required for first argument' 13 | ) 14 | } 15 | 16 | return !predOrFunc(pred, x) 17 | } 18 | 19 | module.exports = curry(not) 20 | -------------------------------------------------------------------------------- /src/combinators/compose2.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | /** compose2 :: (c -> d -> e) -> (a -> c) -> (b -> d) -> a -> b -> e */ 8 | function compose2(f, g, h, x, y) { 9 | if(!isFunction(f) || !isFunction(g) || !isFunction(h)) { 10 | throw new TypeError('compose2: First, second and third arguments must be functions') 11 | } 12 | 13 | return curry(f)(g(x), h(y)) 14 | } 15 | 16 | module.exports = curry(compose2) 17 | -------------------------------------------------------------------------------- /src/combinators/converge.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Matt Ross (amsross) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | // converge (Phoenix or Starling Prime) 8 | // (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d 9 | function converge(f, g, h, x) { 10 | if(!isFunction(f) || !isFunction(g) || !isFunction(h)) { 11 | throw new TypeError('converge: Functions required for first three arguments') 12 | } 13 | 14 | return curry(f)(g(x), h(x)) 15 | } 16 | 17 | module.exports = curry(converge) 18 | -------------------------------------------------------------------------------- /src/helpers/partial.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | /** partial :: ((* -> c), *) -> * -> c */ 8 | function partial(...args) { 9 | const fn = args[0] 10 | const xs = args.slice(1) 11 | 12 | if(!isFunction(fn)) { 13 | throw new TypeError('partial: Function required for first argument') 14 | } 15 | 16 | return curry( 17 | Function.bind.apply(fn, [ null ].concat(xs)) 18 | ) 19 | } 20 | 21 | module.exports = partial 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A simple description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | or a [Repl](http://repl.it/languages/babel) showing the bug, bonus points if it has tests ;) 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Additional context** 23 | Add any other context about the problem here. 24 | -------------------------------------------------------------------------------- /src/core/predOrFunc.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | const sinon = require('sinon') 3 | 4 | const isFunction = require('./isFunction') 5 | const predOrFunc = require('./predOrFunc') 6 | 7 | test('predOrFunc internal', t => { 8 | t.ok(isFunction(predOrFunc), 'is a function') 9 | 10 | const f = sinon.spy() 11 | const P = { runWith: sinon.spy() } 12 | 13 | predOrFunc(f, 'func') 14 | predOrFunc(P, 'pred') 15 | 16 | t.ok(f.calledWith('func'), 'calls the function, passing the argument') 17 | t.ok(P.runWith.calledWith('pred'), 'calls the `runWith` function on Pred, passing the argument') 18 | 19 | t.end() 20 | }) 21 | -------------------------------------------------------------------------------- /src/combinators/substitution.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | // Substitution (Starling) 8 | /** substitution :: (a -> b -> c) -> (a -> b) -> a -> c */ 9 | function substitution(f, g, x) { 10 | if(!(isFunction(f) && isFunction(g))) { 11 | throw new TypeError( 12 | 'substitution: Functions required for first two arguments' 13 | ) 14 | } 15 | 16 | return curry(f)(x, g(x)) 17 | } 18 | 19 | module.exports = curry(substitution) 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/refactor-move-task.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Refactor Task 3 | about: A task to refactor a portion of `crocks` 4 | 5 | --- 6 | 7 | ### Description/Location 8 | 9 | **location:** './helpers/aThing.js' 10 | **description:** 11 | 12 | ### Task List 13 | 14 | * [ ] Moved the main files 15 | * [ ] Moved and updated the tests 16 | * [ ] Moved and updated the documentation 17 | * [ ] Marked original location as obsolete 18 | * [ ] Updated the documentation for obsolete status and pointed to new docs 19 | 20 | For more information, see the `CONTRIBUTING` guide. 21 | 22 | ### Further info 23 | 24 | Any further info that may be relevant... 25 | -------------------------------------------------------------------------------- /src/pointfree/alt.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const fl = require('../core/flNames') 6 | const isAlt = require('../core/isAlt') 7 | const isSameType = require('../core/isSameType') 8 | 9 | /** alt :: Alt m => m a -> m a -> m a */ 10 | function alt(m, x) { 11 | if(!(isAlt(m) && isSameType(m, x))) { 12 | throw new TypeError( 13 | 'alt: Both arguments must be Alts of the same type' 14 | ) 15 | } 16 | 17 | return (x[fl.alt] || x.alt).call(x, m) 18 | } 19 | 20 | module.exports = curry(alt) 21 | -------------------------------------------------------------------------------- /src/pointfree/concat.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isSameType = require('../core/isSameType') 6 | const isSemigroup = require('../core/isSemigroup') 7 | const fl = require('../core/flNames') 8 | 9 | function concat(x, m) { 10 | if(!(isSemigroup(m) && isSameType(x, m))) { 11 | throw new TypeError( 12 | 'concat: Semigroups of the same type required for both arguments' 13 | ) 14 | } 15 | 16 | return (m[fl.concat] || m.concat).call(m, x) 17 | } 18 | 19 | module.exports = curry(concat) 20 | -------------------------------------------------------------------------------- /src/pointfree/reduceRight.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function reduceRight(fn, init, m) { 8 | if(!isFunction(fn)) { 9 | throw new TypeError('reduceRight: Function required for first argument') 10 | } 11 | else if(!(m && isFunction(m.reduceRight))) { 12 | throw new TypeError('reduceRight: Right Foldable required for third argument') 13 | } 14 | 15 | return m.reduceRight(fn, init) 16 | } 17 | 18 | module.exports = curry(reduceRight) 19 | -------------------------------------------------------------------------------- /src/combinators/composeB.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const compose = require('../core/compose') 5 | const curry = require('../core/curry') 6 | const isFunction = require('../core/isFunction') 7 | 8 | // Composition (Bluebird) 9 | /** composeB :: (b -> c) -> (a -> b) -> a -> c */ 10 | function composeB(f, g) { 11 | if(!(isFunction(f) && isFunction(g))) { 12 | throw new TypeError( 13 | 'composeB: Functions required for first two arguments' 14 | ) 15 | } 16 | 17 | return compose(f, g) 18 | } 19 | 20 | module.exports = curry(composeB) 21 | -------------------------------------------------------------------------------- /src/pointfree/fold.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const _array = require('../core/array') 5 | 6 | const isArray = require('../core/isArray') 7 | const isFunction = require('../core/isFunction') 8 | 9 | /** fold :: Foldable f, Semigroup s => f s -> s */ 10 | function fold(m) { 11 | if(isArray(m)) { 12 | return _array.fold(m) 13 | } 14 | 15 | if(m && isFunction(m.fold)) { 16 | return m.fold() 17 | } 18 | 19 | throw new TypeError('fold: Non-empty Foldable with at least one Semigroup is required') 20 | } 21 | 22 | module.exports = fold 23 | -------------------------------------------------------------------------------- /src/pointfree/either.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function either(lf, rf, m) { 8 | if(!(isFunction(lf) && isFunction(rf))) { 9 | throw new TypeError( 10 | 'either: First two arguments must be functions' 11 | ) 12 | } 13 | 14 | if(!(m && isFunction(m.either))) { 15 | throw new TypeError( 16 | 'either: Last argument must be a Sum Type' 17 | ) 18 | } 19 | 20 | return m.either(lf, rf) 21 | } 22 | 23 | module.exports = curry(either) 24 | -------------------------------------------------------------------------------- /src/pointfree/swap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function swap(f, g, m) { 8 | if(!(isFunction(f) && isFunction(g))) { 9 | throw new TypeError( 10 | 'swap: Function required for first two arguments' 11 | ) 12 | } 13 | 14 | if(m && isFunction(m.swap)) { 15 | return m.swap(f, g) 16 | } 17 | 18 | throw new TypeError( 19 | 'swap: Async, Either, Pair or Result required for third arguments' 20 | ) 21 | } 22 | 23 | module.exports = curry(swap) 24 | -------------------------------------------------------------------------------- /src/pointfree/coalesce.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | function coalesce(f, g, m) { 8 | if(!(isFunction(f) && isFunction(g))) { 9 | throw new TypeError( 10 | 'coalesce: Functions required for first two arguments' 11 | ) 12 | } 13 | 14 | if(m && isFunction(m.coalesce)) { 15 | return m.coalesce(f, g) 16 | } 17 | 18 | throw new TypeError( 19 | 'coalesce: Sum Type required for third argument' 20 | ) 21 | } 22 | 23 | module.exports = curry(coalesce) 24 | -------------------------------------------------------------------------------- /src/pointfree/tail.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | const isNil = require('../core/isNil') 6 | 7 | const { Nothing, Just } = require('../core/Maybe') 8 | 9 | function tail(m) { 10 | if(!isNil(m)) { 11 | if(isFunction(m.tail)) { 12 | return m.tail() 13 | } 14 | 15 | if(isFunction(m.slice)) { 16 | return m.length < 2 17 | ? Nothing() 18 | : Just(m.slice(1)) 19 | } 20 | } 21 | 22 | throw new TypeError('tail: Array, String or List required') 23 | } 24 | 25 | module.exports = tail 26 | -------------------------------------------------------------------------------- /src/logic/and.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isPredOrFunc = require('../core/isPredOrFunc') 6 | const predOrFunc = require('../core/predOrFunc') 7 | 8 | /** and :: (a -> Boolean) | Pred -> (a -> Boolean) | Pred -> a -> Boolean */ 9 | function and(f, g) { 10 | if(!(isPredOrFunc(f) && isPredOrFunc(g))) { 11 | throw new TypeError( 12 | 'and: Preds or predicate functions required for first two arguments' 13 | ) 14 | } 15 | 16 | return x => !!(predOrFunc(f, x) && predOrFunc(g, x)) 17 | } 18 | 19 | module.exports = curry(and) 20 | -------------------------------------------------------------------------------- /src/pointfree/init.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author RichardForrester */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | const isNil = require('../core/isNil') 6 | 7 | const { Nothing, Just } = require('../core/Maybe') 8 | 9 | function init(m) { 10 | if(!isNil(m)) { 11 | if(isFunction(m.init)) { 12 | return m.init() 13 | } 14 | 15 | if(isFunction(m.slice)) { 16 | return m.length < 2 17 | ? Nothing() 18 | : Just(m.slice(0, -1)) 19 | } 20 | } 21 | 22 | throw new TypeError('init: Argument must be an Array, String, or List') 23 | } 24 | 25 | module.exports = init 26 | -------------------------------------------------------------------------------- /src/Pair/toPairs.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const List = require('../core/List') 5 | const Pair = require('../core/Pair') 6 | const isObject = require('../core/isObject') 7 | 8 | /** toPairs :: Object -> List (Pair String a) */ 9 | function toPairs(obj) { 10 | if(!isObject(obj)) { 11 | throw new TypeError('toPairs: Argument must be an Object') 12 | } 13 | 14 | return Object.keys(obj).reduce( 15 | (acc, key) => obj[key] !== undefined 16 | ? acc.concat(List.of(Pair(key, obj[key]))) 17 | : acc, 18 | List.empty() 19 | ) 20 | } 21 | 22 | module.exports = toPairs 23 | -------------------------------------------------------------------------------- /src/logic/or.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isPredOrFunc = require('../core/isPredOrFunc') 6 | const predOrFunc = require('../core/predOrFunc') 7 | 8 | /** or :: (a -> Boolean) | Pred -> (a -> Boolean) | Pred -> a -> Boolean */ 9 | function or(f, g) { 10 | if(!(isPredOrFunc(f) && isPredOrFunc(g))) { 11 | throw new TypeError( 12 | 'or: Preds or predicate functions required for first two arguments' 13 | ) 14 | } 15 | 16 | return x => 17 | !!(predOrFunc(f, x) || predOrFunc(g, x)) 18 | } 19 | 20 | module.exports = curry(or) 21 | -------------------------------------------------------------------------------- /src/core/compose.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | const sinon = require('sinon') 3 | 4 | const identity = x => x 5 | 6 | const compose = require('./compose') 7 | 8 | test('compose core', t => { 9 | const f = sinon.spy(identity) 10 | const g = sinon.spy(identity) 11 | const x = 74 12 | 13 | const result = compose(f, g)(x) 14 | 15 | t.ok(f.calledAfter(g), 'calls second function before the first') 16 | t.ok(g.calledWith(x), 'third argument passed into second function') 17 | t.ok(f.calledWith(g.returnValues[0]), 'first function passed result of second function') 18 | t.equal(result, f.returnValues[0], 'returns the result of the first function') 19 | 20 | t.end() 21 | }) 22 | -------------------------------------------------------------------------------- /src/Maybe/safe.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const { Nothing, Just } = require('../core/Maybe') 5 | const predOrFunc = require('../core/predOrFunc') 6 | 7 | const curry = require('../core/curry') 8 | const isPredOrFunc = require('../core/isPredOrFunc') 9 | 10 | /** safe :: ((a -> Boolean) | Pred) -> a -> Maybe a */ 11 | function safe(pred, x) { 12 | if(!isPredOrFunc(pred)) { 13 | throw new TypeError('safe: Pred or predicate function required for first argument') 14 | } 15 | 16 | return predOrFunc(pred, x) 17 | ? Just(x) 18 | : Nothing() 19 | } 20 | 21 | module.exports = curry(safe) 22 | -------------------------------------------------------------------------------- /src/logic/implies.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isPredOrFunc = require('../core/isPredOrFunc') 6 | const predOrFunc = require('../core/predOrFunc') 7 | 8 | /** implies :: (a -> Boolean) | Pred -> (a -> Boolean) -> a -> Boolean */ 9 | function implies(p, q) { 10 | if(!(isPredOrFunc(p) && isPredOrFunc(q))) { 11 | throw new TypeError( 12 | 'implies: Preds or predicate functions required for first two arguments' 13 | ) 14 | } 15 | 16 | return x => !predOrFunc(p, x) || !!predOrFunc(q, x) 17 | } 18 | 19 | module.exports = curry(implies) 20 | -------------------------------------------------------------------------------- /src/Result/tryCatch.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const { Err, Ok } = require('.') 5 | const curry = require('../core/curry') 6 | const isFunction = require('../core/isFunction') 7 | 8 | function tryCatch(fn) { 9 | if(!isFunction(fn)) { 10 | throw new TypeError('tryCatch: Function required for first argument') 11 | } 12 | 13 | const safe = function() { 14 | try { return Ok(fn.apply(this, arguments)) } 15 | catch(e) { return Err(e) } 16 | } 17 | 18 | Object.defineProperty(safe, 'length', { value: fn.length }) 19 | 20 | return safe 21 | } 22 | 23 | module.exports = curry(tryCatch) 24 | -------------------------------------------------------------------------------- /src/core/isEmpty.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | const isObject = require('./isObject') 4 | const isMonoid = require('./isMonoid') 5 | const equals = require('./equals') 6 | const fl = require('./flNames') 7 | 8 | function isEmpty(x) { 9 | if(isMonoid(x)) { 10 | const empty = x.constructor[fl['empty']] || x.constructor['empty'] || x['empty'] 11 | 12 | return equals(x, empty()) 13 | } 14 | 15 | if(isObject(x)) { 16 | return !Object.keys(x).length 17 | } 18 | 19 | if(x && x.length !== undefined) { 20 | return !x.length 21 | } 22 | 23 | return true 24 | } 25 | 26 | module.exports = isEmpty 27 | -------------------------------------------------------------------------------- /src/core/mconcatMap.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const Last = require('../test/LastMonoid') 4 | const isFunction = require('./isFunction') 5 | 6 | const mconcatMap = require('./mconcatMap') 7 | 8 | test('mconcatMap core', t => { 9 | t.ok(isFunction(mconcatMap), 'is a function') 10 | 11 | const addOne = x => x + 1 12 | const nothing = mconcatMap(Last, addOne, []) 13 | const something = mconcatMap(Last, addOne, [ 1, 2, 3 ]) 14 | 15 | t.equal(nothing.valueOf(), Last.empty().valueOf(), 'returns the empty value when passed an empty array') 16 | t.equal(something.valueOf(), 4, 'returns the last value by lifting and calling concat on each after running through map function') 17 | 18 | t.end() 19 | }) 20 | -------------------------------------------------------------------------------- /src/helpers/nAry.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const curryN = require('../core/curryN') 6 | const isFunction = require('../core/isFunction') 7 | const isNumber = require('../core/isNumber') 8 | 9 | /** nAry :: Number -> (* -> a) -> * -> * -> a */ 10 | function nAry(num, fn) { 11 | if(!isNumber(num)) { 12 | throw new TypeError('nAry: Number required for first argument') 13 | } 14 | 15 | if(!isFunction(fn)) { 16 | throw new TypeError('nAry: Function required for second argument') 17 | } 18 | 19 | return curryN(num, fn) 20 | } 21 | 22 | module.exports = curry(nAry) 23 | -------------------------------------------------------------------------------- /src/logic/index.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const index = require('.') 4 | 5 | const and = require('./and') 6 | const ifElse = require('./ifElse') 7 | const not = require('./not') 8 | const or = require('./or') 9 | const unless = require('./unless') 10 | const when = require('./when') 11 | 12 | test('logic entry', t => { 13 | 14 | t.equal(index.and, and, 'provides the and logic') 15 | t.equal(index.ifElse, ifElse, 'provides the ifElse logic') 16 | t.equal(index.not, not, 'provides the not logic') 17 | t.equal(index.or, or, 'provides the or logic') 18 | t.equal(index.unless, unless, 'provides the unless logic') 19 | t.equal(index.when, when, 'provides the when logic') 20 | 21 | t.end() 22 | }) 23 | -------------------------------------------------------------------------------- /src/test/LastMonoid.js: -------------------------------------------------------------------------------- 1 | const _implements = require('../core/implements') 2 | const _inspect = require('../core/inspect') 3 | 4 | const constant = x => () => x 5 | const identity = x => x 6 | 7 | const typeString = 'crocks/Last@1' 8 | const _type = constant('Last') 9 | 10 | function LastMonoid(x) { 11 | return { 12 | inspect: constant('Last' + _inspect(x)), 13 | concat: identity, 14 | valueOf: constant(x), 15 | type: _type, 16 | ['@@type']: typeString 17 | } 18 | } 19 | 20 | LastMonoid.empty = () => LastMonoid(null) 21 | LastMonoid.type = _type 22 | LastMonoid['@@type'] = typeString 23 | 24 | LastMonoid['@@implements'] = _implements( 25 | [ 'concat', 'empty' ] 26 | ) 27 | 28 | module.exports = LastMonoid 29 | -------------------------------------------------------------------------------- /src/core/flNames.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | module.exports = { 5 | alt: 'fantasy-land/alt', 6 | bimap: 'fantasy-land/bimap', 7 | chain: 'fantasy-land/chain', 8 | compose: 'fantasy-land/compose', 9 | concat: 'fantasy-land/concat', 10 | contramap: 'fantasy-land/contramap', 11 | empty: 'fantasy-land/empty', 12 | equals: 'fantasy-land/equals', 13 | extend: 'fantasy-land/extend', 14 | filter: 'fantasy-land/filter', 15 | id: 'fantasy-land/id', 16 | map: 'fantasy-land/map', 17 | of: 'fantasy-land/of', 18 | promap: 'fantasy-land/promap', 19 | reduce: 'fantasy-land/reduce', 20 | zero: 'fantasy-land/zero' 21 | } 22 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Crocks 2 | 3 | [![Built with Electric](https://img.shields.io/badge/built%20with-electric-f3c302.svg?style=flat)](http://electricjs.com) 4 | 5 | ## Setup 6 | 7 | 1. Make sure you have [node and npm](https://nodejs.org/en/download/) installed: 8 | 9 | ```sh 10 | node -v && npm -v 11 | ``` 12 | 13 | 2. Install our global dependencies: 14 | 15 | ```sh 16 | [sudo] npm i -g electric-cli 17 | ``` 18 | 19 | 3. Install our local dependencies: 20 | 21 | ```sh 22 | npm i 23 | ``` 24 | 25 | ## Usage 26 | 27 | * Build the site, serve it locally, and watch for any changes: 28 | 29 | ``` 30 | electric run 31 | ``` 32 | 33 | * Deploy to production (send build files to `wedeploy` branch): 34 | 35 | ``` 36 | electric deploy 37 | ``` 38 | -------------------------------------------------------------------------------- /src/pointfree/bichain.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | /** bichain :: bichain m => (e -> m c b) -> (a -> m c b) -> m e a -> m c b */ 8 | function bichain(f, g, m) { 9 | if(!isFunction(f) || !isFunction(g)) { 10 | throw new TypeError('bichain: First two arguments must be Sum Type returning functions') 11 | } 12 | 13 | if(m && isFunction(m.bichain)) { 14 | return m.bichain.call(m, f, g) 15 | } 16 | 17 | throw new TypeError( 18 | 'bichain: Third argument must be a Sum Type' 19 | ) 20 | } 21 | 22 | module.exports = curry(bichain) 23 | -------------------------------------------------------------------------------- /src/pointfree/extend.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const fl = require('../core/flNames') 6 | const isExtend = require('../core/isExtend') 7 | const isFunction = require('../core/isFunction') 8 | 9 | /** extend :: Extend w => (w a -> b) -> w a -> w b */ 10 | function extend(fn, m) { 11 | if(!isFunction(fn)) { 12 | throw new TypeError('extend: Function required for first argument') 13 | } 14 | if(!isExtend(m)) { 15 | throw new TypeError('extend: Extend required for second argument') 16 | } 17 | 18 | return (m[fl.extend] || m.extend).call(m, fn) 19 | } 20 | 21 | module.exports = curry(extend) 22 | -------------------------------------------------------------------------------- /src/core/innerConcat.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isSameType = require('./isSameType') 5 | const isSemigroup = require('./isSemigroup') 6 | 7 | function innerConcat(method, m) { 8 | return function(left) { 9 | if(!isSemigroup(left)) { 10 | throw new TypeError(`${method}: Both containers must contain Semigroups of the same type`) 11 | } 12 | 13 | return m.map(right => { 14 | if(!isSameType(left, right)) { 15 | throw new TypeError(`${method}: Both containers must contain Semigroups of the same type`) 16 | } 17 | 18 | return left.concat(right) 19 | }) 20 | } 21 | } 22 | 23 | module.exports = innerConcat 24 | -------------------------------------------------------------------------------- /src/pointfree/both.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Pair = require('../core/types').proxy('Pair') 5 | 6 | const isFunction = require('../core/isFunction') 7 | const isSameType = require('../core/isSameType') 8 | 9 | function both(m) { 10 | if(isFunction(m)) { 11 | return function(x) { 12 | if(!isSameType(Pair, x)) { 13 | throw new TypeError('both: Pair required as input') 14 | } 15 | 16 | return x.bimap(m, m) 17 | } 18 | } 19 | 20 | if(m && isFunction(m.both)) { 21 | return m.both() 22 | } 23 | 24 | throw new TypeError('both: Strong Function or Profunctor required') 25 | } 26 | 27 | module.exports = both 28 | -------------------------------------------------------------------------------- /src/pointfree/reduce.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFoldable = require('../core/isFoldable') 6 | const isFunction = require('../core/isFunction') 7 | const fl = require('../core/flNames') 8 | 9 | function reduce(fn, init, m) { 10 | if(!isFunction(fn)) { 11 | throw new TypeError( 12 | 'reduce: Function required for first argument' 13 | ) 14 | } 15 | 16 | if(!isFoldable(m)) { 17 | throw new TypeError( 18 | 'reduce: Foldable required for third argument' 19 | ) 20 | } 21 | 22 | return (m[fl.reduce] || m.reduce).call(m, fn, init) 23 | } 24 | 25 | module.exports = curry(reduce) 26 | -------------------------------------------------------------------------------- /src/pointfree/ap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const array = require('../core/array') 5 | const curry = require('../core/curry') 6 | const isApplicative = require('../core/isApplicative') 7 | const isArray = require('../core/isArray') 8 | const isSameType = require('../core/isSameType') 9 | 10 | /** ap :: Applicative m => m a -> m (a -> b) -> m b */ 11 | function ap(m, x) { 12 | if(!((isApplicative(m) || isArray(m)) && isSameType(m, x))) { 13 | throw new TypeError('ap: Both arguments must be Applys of the same type') 14 | } 15 | 16 | if(isArray(x)) { 17 | return array.ap(m, x) 18 | } 19 | 20 | return x.ap(m) 21 | } 22 | 23 | module.exports = curry(ap) 24 | -------------------------------------------------------------------------------- /src/pointfree/bimap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isBifunctor = require('../core/isBifunctor') 6 | const isFunction = require('../core/isFunction') 7 | const fl = require('../core/flNames') 8 | 9 | function bimap(f, g, m) { 10 | if(!(isFunction(f) && isFunction(g))) { 11 | throw new TypeError( 12 | 'bimap: Functions required for first two arguments' 13 | ) 14 | } 15 | 16 | if(!isBifunctor(m)) { 17 | throw new TypeError( 18 | 'bimap: Bifunctor required for third argument' 19 | ) 20 | } 21 | 22 | return (m[fl.bimap] || m.bimap).call(m, f, g) 23 | } 24 | 25 | module.exports = curry(bimap) 26 | -------------------------------------------------------------------------------- /src/pointfree/first.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Pair = require('../core/types').proxy('Pair') 5 | 6 | const isFunction = require('../core/isFunction') 7 | const isSameType = require('../core/isSameType') 8 | 9 | const identity = x => x 10 | 11 | function first(m) { 12 | if(isFunction(m)) { 13 | return function(x) { 14 | if(!isSameType(Pair, x)) { 15 | throw new TypeError('first: Pair required as input') 16 | } 17 | 18 | return x.bimap(m, identity) 19 | } 20 | } 21 | 22 | if(m && isFunction(m.first)) { 23 | return m.first() 24 | } 25 | 26 | throw new TypeError('first: Arrow, Function or Star required') 27 | } 28 | 29 | module.exports = first 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2016, Ian Hofmann-Hicks 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A description of what the problem is. Ex. Based on my understanding of _monad_ as shown here [...] I think we're missing _feature_ feature 9 | 10 | **Describe the solution you'd like** 11 | A description of what you'd like to have added to the project. 12 | 13 | **Describe alternatives for how you do this now** 14 | Do you have a work around for how your currently doing this? 15 | 16 | **Code** 17 | Do you have example code or tests in a [Repl](http://repl.it/languages/babel) for what you'd like added? 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /src/pointfree/second.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Pair = require('../core/types').proxy('Pair') 5 | 6 | const isFunction = require('../core/isFunction') 7 | const isSameType = require('../core/isSameType') 8 | 9 | const identity = x => x 10 | 11 | function second(m) { 12 | if(isFunction(m)) { 13 | return function(x) { 14 | if(!isSameType(Pair, x)) { 15 | throw new TypeError('second: Pair required as input') 16 | } 17 | 18 | return x.bimap(identity, m) 19 | } 20 | } 21 | 22 | if(m && isFunction(m.second)) { 23 | return m.second() 24 | } 25 | 26 | throw new TypeError('second: Strong Function or Profunctor required') 27 | } 28 | 29 | module.exports = second 30 | -------------------------------------------------------------------------------- /src/helpers/mconcat.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFoldable = require('../core/isFoldable') 6 | const isMonoid = require('../core/isMonoid') 7 | const mconcatMap = require('../core/mconcatMap') 8 | 9 | const identity = x => x 10 | 11 | /** mconcat :: Monoid m => m -> ([ a ] | List a) -> m a */ 12 | function mconcat(m, xs) { 13 | if(!isMonoid(m)) { 14 | throw new TypeError( 15 | 'mconcat: Monoid required for first argument' 16 | ) 17 | } 18 | 19 | if(!isFoldable(xs)) { 20 | throw new TypeError( 21 | 'mconcat: Foldable required for second argument' 22 | ) 23 | } 24 | 25 | return mconcatMap(m, identity, xs) 26 | } 27 | 28 | module.exports = curry(mconcat) 29 | -------------------------------------------------------------------------------- /src/helpers/mreduce.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFoldable = require('../core/isFoldable') 6 | const isMonoid = require('../core/isMonoid') 7 | const mconcatMap = require('../core/mconcatMap') 8 | 9 | const identity = x => x 10 | 11 | /** mreduce :: Monoid M => M -> ([ a ] | List a) -> a */ 12 | function mreduce(m, xs) { 13 | if(!isMonoid(m)) { 14 | throw new TypeError( 15 | 'mreduce: Monoid required for first argument' 16 | ) 17 | } 18 | 19 | if(!isFoldable(xs)) { 20 | throw new TypeError( 21 | 'mreduce: Foldable required for second argument' 22 | ) 23 | } 24 | 25 | return mconcatMap(m, identity, xs).valueOf() 26 | } 27 | 28 | module.exports = curry(mreduce) 29 | -------------------------------------------------------------------------------- /src/logic/when.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const predOrFunc = require('../core/predOrFunc') 6 | const isPredOrFunc = require('../core/isPredOrFunc') 7 | const isFunction = require('../core/isFunction') 8 | 9 | /** when :: (a -> Boolean) | Pred -> (a -> b) -> a -> b | a */ 10 | function when(pred, f) { 11 | if(!isPredOrFunc(pred)) { 12 | throw new TypeError( 13 | 'when: Pred or predicate function required for first argument' 14 | ) 15 | } 16 | 17 | if(!isFunction(f)) { 18 | throw new TypeError( 19 | 'when: Function required for second argument' 20 | ) 21 | } 22 | 23 | return x => 24 | predOrFunc(pred, x) ? f(x) : x 25 | } 26 | 27 | module.exports = curry(when) 28 | -------------------------------------------------------------------------------- /src/Maybe/safeAfter.js: -------------------------------------------------------------------------------- 1 | const { Just, Nothing } = require('../core/Maybe') 2 | 3 | const curry = require('../core/curry') 4 | const isPredOrFunc = require('../core/isPredOrFunc') 5 | const isFunction = require('../core/isFunction') 6 | const predOrFunc = require('../core/predOrFunc') 7 | 8 | /** safeAfter :: ((b -> Boolean) | Pred) -> (a -> b) -> a -> Maybe b */ 9 | function safeAfter(pred, fn) { 10 | if(!isPredOrFunc(pred)) { 11 | throw new TypeError('safeAfter: Pred or predicate function required for first argument') 12 | } 13 | if(!isFunction(fn)) { 14 | throw new TypeError('safeAfter: Function required for second argument') 15 | } 16 | 17 | return x => { 18 | const result = fn(x) 19 | return predOrFunc(pred, result) 20 | ? Just(result) 21 | : Nothing() 22 | } 23 | } 24 | 25 | module.exports = curry(safeAfter) 26 | -------------------------------------------------------------------------------- /src/logic/unless.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isPredOrFunc = require('../core/isPredOrFunc') 6 | const isFunction = require('../core/isFunction') 7 | const predOrFunc = require('../core/predOrFunc') 8 | 9 | /** unless :: (a -> Boolean) | Pred -> (a -> b) -> a | b */ 10 | function unless(pred, f) { 11 | if(!isPredOrFunc(pred)) { 12 | throw new TypeError( 13 | 'unless: Pred or predicate function required for first argument' 14 | ) 15 | } 16 | 17 | if(!isFunction(f)) { 18 | throw new TypeError( 19 | 'unless: Function required for second argument' 20 | ) 21 | } 22 | 23 | return x => 24 | !predOrFunc(pred, x) ? f(x) : x 25 | } 26 | 27 | module.exports = curry(unless) 28 | -------------------------------------------------------------------------------- /src/pointfree/empty.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const hasAlg = require('../core/hasAlg') 5 | const isSameType = require('../core/isSameType') 6 | const fl = require('../core/flNames') 7 | 8 | function empty(m) { 9 | if(m && hasAlg('empty', m)) { 10 | return (m[fl.empty] || m.empty).call(m) 11 | } 12 | 13 | if(m && hasAlg('empty', m.constructor)) { 14 | return (m.constructor[fl.empty] || m.constructor.empty).call(m) 15 | } 16 | 17 | if(isSameType([], m)) { 18 | return [] 19 | } 20 | 21 | if(isSameType('', m)) { 22 | return '' 23 | } 24 | 25 | if(isSameType({}, m)) { 26 | return {} 27 | } 28 | 29 | throw new TypeError('empty: Monoid, Array, String or Object required') 30 | } 31 | 32 | module.exports = empty 33 | -------------------------------------------------------------------------------- /src/predicates/hasProp.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isDefined = require('../core/isDefined') 6 | const isEmpty = require('../core/isEmpty') 7 | const isInteger = require('../core/isInteger') 8 | const isNil = require('../core/isNil') 9 | const isString = require('../core/isString') 10 | 11 | /** hasProp :: (String | Integer) -> a -> Boolean */ 12 | function hasProp(key, x) { 13 | if(!(isString(key) && !isEmpty(key) || isInteger(key))) { 14 | throw new TypeError( 15 | 'hasProp: Non-empty String or Integer required for first argument' 16 | ) 17 | } 18 | 19 | if(isNil(x)) { 20 | return false 21 | } 22 | 23 | return isDefined(x[key]) 24 | } 25 | 26 | module.exports = curry(hasProp) 27 | -------------------------------------------------------------------------------- /src/Async/asyncToPromise.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Dale Francis */ 3 | 4 | const curry = require('../core/curry') 5 | const isSameType = require('../core/isSameType') 6 | const isFunction = require('../core/isFunction') 7 | 8 | const Async = require('../core/types').proxy('Async') 9 | 10 | const toPromise = m => { 11 | if(!isSameType(Async, m)) { 12 | throw new TypeError('asyncToPromise: Argument must be an Async or a Function that returns an Async') 13 | } 14 | 15 | return m.toPromise() 16 | } 17 | 18 | /** asyncToPromise :: m e a -> Promise a e */ 19 | /** asyncToPromise :: (a -> m e b) -> a -> Promise b e */ 20 | function asyncToPromise(m) { 21 | return isFunction(m) 22 | ? x => toPromise(m(x)) 23 | : toPromise(m) 24 | } 25 | 26 | module.exports = curry(asyncToPromise) 27 | -------------------------------------------------------------------------------- /src/helpers/pipe.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | 6 | const err = 'pipe: Functions required' 7 | 8 | function applyPipe(f, g) { 9 | if(!isFunction(g)) { 10 | throw new TypeError(err) 11 | } 12 | 13 | return function(...args) { 14 | return g.call(null, f.apply(null, args)) 15 | } 16 | } 17 | 18 | /** pipe :: ((a -> b), (b -> c), ..., (y -> z)) -> a -> z */ 19 | function pipe(...fns) { 20 | if(!arguments.length) { 21 | throw new TypeError(err) 22 | } 23 | 24 | const head = 25 | fns[0] 26 | 27 | if(!isFunction(head)) { 28 | throw new TypeError(err) 29 | } 30 | 31 | const tail = 32 | fns.slice(1).concat(x => x) 33 | 34 | return tail.reduce(applyPipe, head) 35 | } 36 | 37 | module.exports = pipe 38 | -------------------------------------------------------------------------------- /src/Maybe/safeLift.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const compose = require('../core/compose') 5 | const curry = require('../core/curry') 6 | const isPredOrFunc = require('../core/isPredOrFunc') 7 | const isFunction = require('../core/isFunction') 8 | const safe = require('./safe') 9 | 10 | const map = 11 | fn => m => m.map(fn) 12 | 13 | /** safeLift :: ((a -> Boolean) | Pred) -> (a -> b) -> a -> Maybe b */ 14 | function safeLift(pred, fn) { 15 | if(!isPredOrFunc(pred)) { 16 | throw new TypeError('safeLift: Pred or predicate function required for first argument') 17 | } 18 | else if(!isFunction(fn)) { 19 | throw new TypeError('safeLift: Function required for second argument') 20 | } 21 | 22 | return compose(map(fn), safe(pred)) 23 | } 24 | 25 | module.exports = curry(safeLift) 26 | -------------------------------------------------------------------------------- /src/logic/ifElse.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | const isPredOrFunc = require('../core/isPredOrFunc') 7 | const predOrFunc = require('../core/predOrFunc') 8 | 9 | /** ifElse :: (a -> Boolean) | Pred -> (a -> b) -> (a -> c) -> a -> (a | c) */ 10 | function ifElse(pred, f, g) { 11 | if(!isPredOrFunc(pred)) { 12 | throw new TypeError( 13 | 'ifElse: Pred or predicate function required for first argument' 14 | ) 15 | } 16 | 17 | if(!(isFunction(f) && isFunction(g))) { 18 | throw new TypeError( 19 | 'ifElse: Functions required for second and third arguments' 20 | ) 21 | } 22 | 23 | return x => predOrFunc(pred, x) ? f(x) : g(x) 24 | } 25 | 26 | module.exports = curry(ifElse) 27 | -------------------------------------------------------------------------------- /src/helpers/mapReduce.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFoldable = require('../core/isFoldable') 6 | const isFunction = require('../core/isFunction') 7 | 8 | function mapReduce(mapFn, reduceFn, empty, xs) { 9 | if(!isFunction(mapFn)) { 10 | throw new TypeError('mapReduce: Unary mapping function required for first argument') 11 | } 12 | 13 | if(!isFunction(reduceFn)) { 14 | throw new TypeError('mapReduce: Binary reduction function required for second argument') 15 | } 16 | 17 | if(!isFoldable(xs)) { 18 | throw new TypeError('mapReduce: Foldable required for fourth argument') 19 | } 20 | 21 | return xs.reduce( 22 | (acc, x) => reduceFn(acc, mapFn(x)), 23 | empty 24 | ) 25 | } 26 | 27 | module.exports = curry(mapReduce) 28 | -------------------------------------------------------------------------------- /src/helpers/pipeS.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isSameType = require('../core/isSameType') 5 | const isSemigroupoid = require('../core/isSemigroupoid') 6 | 7 | const err = 'pipeS: Semigroupoids of the same type required' 8 | 9 | /** pipeS :: Semigroupoid s => (s a b, s b c, ..., s y z) -> s a z */ 10 | function pipeS(...ms) { 11 | if(!arguments.length) { 12 | throw new TypeError(err) 13 | } 14 | 15 | const head = 16 | ms[0] 17 | 18 | if(!isSemigroupoid(head)) { 19 | throw new TypeError(err) 20 | } 21 | 22 | if(ms.length === 1) { 23 | return head 24 | } 25 | 26 | return ms.slice().reduce((comp, m) => { 27 | if(!isSameType(comp, m)) { 28 | throw new TypeError(err) 29 | } 30 | 31 | return comp.compose(m) 32 | }) 33 | } 34 | 35 | module.exports = pipeS 36 | -------------------------------------------------------------------------------- /src/Tuple/tupleToArray.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Jasmina Jacquelina (jasminabasurita) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | /** tupleToArray :: Tuple a -> [ a ] */ 8 | /** tupleToArray :: (a -> Tuple b) -> a -> [ b ] */ 9 | function tupleToArray(tuple) { 10 | if(isFunction(tuple)) { 11 | return function(x) { 12 | const m = tuple(x) 13 | 14 | if(!isFunction(m.tupleLength)) { 15 | throw new TypeError('tupleToArray: Tuple returning function required') 16 | } 17 | 18 | return m.toArray() 19 | } 20 | } 21 | 22 | if(isFunction(tuple.tupleLength)) { 23 | return tuple.toArray() 24 | } 25 | 26 | throw new TypeError('tupleToArray: Tuple or Tuple returning function required') 27 | } 28 | 29 | module.exports = curry(tupleToArray) 30 | 31 | -------------------------------------------------------------------------------- /src/pointfree/promap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const compose = require('../core/compose') 5 | const curry = require('../core/curry') 6 | const fl = require('../core/flNames') 7 | const isFunction = require('../core/isFunction') 8 | const isProfunctor = require('../core/isProfunctor') 9 | 10 | function promap(l, r, m) { 11 | if(!(isFunction(l) && isFunction(r))) { 12 | throw new TypeError( 13 | 'promap: Functions required for first two arguments' 14 | ) 15 | } 16 | 17 | if(isFunction(m)) { 18 | return compose(compose(r, m), l) 19 | } 20 | 21 | if(isProfunctor(m)) { 22 | return (m[fl.promap] || m.promap).call(m, l, r) 23 | } 24 | 25 | throw new TypeError( 26 | 'promap: Function or Profunctor required for third argument' 27 | ) 28 | } 29 | 30 | module.exports = curry(promap) 31 | -------------------------------------------------------------------------------- /src/pointfree/sequence.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const array = require('../core/array') 5 | const curry = require('../core/curry') 6 | const isArray = require('../core/isArray') 7 | const isApplicative = require('../core/isApplicative') 8 | const isFunction = require('../core/isFunction') 9 | 10 | function sequence(af, m) { 11 | if(!(isApplicative(af) || isFunction(af))) { 12 | throw new TypeError( 13 | 'sequence: Applicative TypeRep or Apply returning function required for first argument' 14 | ) 15 | } 16 | 17 | if(m && isFunction(m.sequence)) { 18 | return m.sequence(af) 19 | } 20 | 21 | if(isArray(m)) { 22 | return array.sequence(af, m) 23 | } 24 | 25 | throw new TypeError('sequence: Traversable or Array required for second argument') 26 | } 27 | 28 | module.exports = curry(sequence) 29 | -------------------------------------------------------------------------------- /src/helpers/omit.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFoldable = require('../core/isFoldable') 6 | const isObject = require('../core/isObject') 7 | 8 | function omitKeys(keys, obj) { 9 | return function(acc, key) { 10 | return keys.indexOf(key) === -1 && obj[key] !== undefined 11 | ? Object.assign(acc, { [key]: obj[key] }) 12 | : acc 13 | } 14 | } 15 | 16 | /** omit :: [ String ] -> Object -> Object */ 17 | function omit(keys, obj) { 18 | if(!isFoldable(keys)) { 19 | throw new TypeError('omit: Foldable required for first argument') 20 | } 21 | else if(!isObject(obj)) { 22 | throw new TypeError('omit: Object required for second argument') 23 | } 24 | 25 | return Object.keys(obj).reduce(omitKeys(keys, obj), {}) 26 | } 27 | 28 | module.exports = curry(omit) 29 | -------------------------------------------------------------------------------- /src/helpers/compose.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | 6 | const err = 'compose: Functions required' 7 | 8 | function applyPipe(f, g) { 9 | if(!isFunction(g)) { 10 | throw new TypeError(err) 11 | } 12 | 13 | return (...args) => 14 | g.call(null, f.apply(null, args)) 15 | } 16 | 17 | /** compose :: ((y -> z), (x -> y), ..., (a -> b)) -> a -> z */ 18 | function compose(...args) { 19 | if(!arguments.length) { 20 | throw new TypeError(err) 21 | } 22 | 23 | const fns = 24 | args.slice().reverse() 25 | 26 | const head = 27 | fns[0] 28 | 29 | if(!isFunction(head)) { 30 | throw new TypeError(err) 31 | } 32 | 33 | const tail = 34 | fns.slice(1).concat(x => x) 35 | 36 | return tail.reduce(applyPipe, head) 37 | } 38 | 39 | module.exports = compose 40 | -------------------------------------------------------------------------------- /src/core/type.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | 5 | const type = require('./type') 6 | 7 | const adt = { type: () => 'Type' } 8 | const fn = x => x 9 | 10 | test('type', t => { 11 | t.ok(isFunction(type, 'is a function')) 12 | 13 | t.equals(type(9), 'Number', 'returns Number for a Number') 14 | t.equals(type(true), 'Boolean', 'returns Boolean for a Boolean') 15 | t.equals(type('nice'), 'String', 'returns String for a String') 16 | t.equals(type([]), 'Array', 'returns Array for an Array') 17 | t.equals(type({}), 'Object', 'returns Object for an Object') 18 | t.equals(type(null), 'Null', 'returns Null for null') 19 | t.equals(type(undefined), 'Undefined', 'returns Undefined for undefined') 20 | t.equals(type(adt), 'Type', 'returns the result of calling type on an adt') 21 | t.equals(type(fn), 'Function', 'returns Function for a function') 22 | 23 | t.end() 24 | }) 25 | -------------------------------------------------------------------------------- /src/List/arrayToList.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const List = require('.') 5 | 6 | const curry = require('../core/curry') 7 | const isArray = require('../core/isArray') 8 | const isFunction = require('../core/isFunction') 9 | 10 | /** arrayToList :: [ a ] -> List a */ 11 | /** arrayToList :: (a -> [ b ]) -> a -> List b */ 12 | function arrayToList(array) { 13 | if(isArray(array)) { 14 | return List.fromArray(array) 15 | } 16 | else if(isFunction(array)) { 17 | return function(x) { 18 | const g = array(x) 19 | 20 | if(!isArray(g)) { 21 | throw new TypeError('arrayToList: Array returning function required') 22 | } 23 | 24 | return List.fromArray(g) 25 | } 26 | } 27 | 28 | throw new TypeError('arrayToList: Array or Array returning function required') 29 | } 30 | 31 | module.exports = curry(arrayToList) 32 | -------------------------------------------------------------------------------- /src/pointfree/chain.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const _chain = require('../core/array').chain 5 | const curry = require('../core/curry') 6 | const isArray = require('../core/isArray') 7 | const isChain = require('../core/isChain') 8 | const isFunction = require('../core/isFunction') 9 | const fl = require('../core/flNames') 10 | 11 | /** chain :: Chain m => (a -> m b) -> m a -> m b */ 12 | function chain(fn, m) { 13 | if(!isFunction(fn)) { 14 | throw new TypeError('chain: Chain returning function required for first argument') 15 | } 16 | 17 | if(!(isChain(m) || isArray(m))) { 18 | throw new TypeError('chain: Chain of the same type required for second argument') 19 | } 20 | 21 | if(isArray(m)) { 22 | return _chain(fn, m) 23 | } 24 | 25 | return (m[fl.chain] || m.chain).call(m, fn) 26 | } 27 | 28 | module.exports = curry(chain) 29 | -------------------------------------------------------------------------------- /src/List/listToArray.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const List = require('.') 5 | 6 | const curry = require('../core/curry') 7 | const isFunction = require('../core/isFunction') 8 | const isSameType = require('../core/isSameType') 9 | 10 | /** listToArray :: List a -> [ a ] */ 11 | /** listToArray :: (a -> List b) -> a -> [ b ] */ 12 | function listToArray(list) { 13 | if(isFunction(list)) { 14 | return function(x) { 15 | const m = list(x) 16 | 17 | if(!isSameType(List, m)) { 18 | throw new TypeError('listToArray: List returning function required') 19 | } 20 | 21 | return m.toArray() 22 | } 23 | } 24 | 25 | if(isSameType(List, list)) { 26 | return list.toArray() 27 | } 28 | 29 | throw new TypeError('listToArray: List or List returning function required') 30 | } 31 | 32 | module.exports = curry(listToArray) 33 | -------------------------------------------------------------------------------- /src/pointfree/foldMap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const _array = require('../core/array') 5 | 6 | const curry = require('../core/curry') 7 | const isArray = require('../core/isArray') 8 | const isFunction = require('../core/isFunction') 9 | 10 | /** foldMap :: Foldable f, Semigroup s => (a -> s) -> f a -> s */ 11 | function foldMap(fn, m) { 12 | if(!isFunction(fn)) { 13 | throw new TypeError( 14 | 'foldMap: Function returning Semigroups of the same type required for first argument' 15 | ) 16 | } 17 | 18 | if(isArray(m)) { 19 | return _array.foldMap(fn, m) 20 | } 21 | 22 | if(m && isFunction(m.foldMap)) { 23 | return m.foldMap(fn) 24 | } 25 | 26 | throw new TypeError( 27 | 'foldMap: Non-empty Foldable with at least one Semigroup required for second argument' 28 | ) 29 | } 30 | 31 | module.exports = curry(foldMap) 32 | -------------------------------------------------------------------------------- /bin/setup.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | var fs = require('fs') 3 | var resolve = require('path').resolve 4 | var join = require('path').join 5 | var cp = require('child_process') 6 | var os = require('os') 7 | 8 | var root = resolve(__dirname, '..') 9 | var docs = resolve(__dirname, '..', 'docs') 10 | var isWindows = os.platform().startsWith('win') 11 | var npmCmd = isWindows ? 'npm.cmd' : 'npm' 12 | var rmrf = isWindows ? 'rd /s /q node_modules' : 'rm -rf node_modules' 13 | 14 | install(root) 15 | install(docs) 16 | 17 | function install(dir) { 18 | console.log('working on ' + dir) 19 | 20 | if (fs.existsSync(join(dir, 'node_modules'))) { 21 | console.log('Found a node_modules folder exists, deleting...') 22 | 23 | cp.execSync(rmrf, { env: process.env, cwd: dir, stdio: 'inherit' }) 24 | } 25 | 26 | console.log('Running npm install...') 27 | cp.spawnSync(npmCmd, [ 'i', '--no-save' ], { env: process.env, cwd: dir, stdio: 'inherit' }) 28 | } 29 | -------------------------------------------------------------------------------- /src/core/apOrFunc.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | const sinon = require('sinon') 3 | 4 | const isFunction = require('./isFunction') 5 | const apOrFunc = require('./apOrFunc') 6 | 7 | const MockCrock = require('../test/MockCrock') 8 | 9 | const oldFn = MockCrock.of 10 | 11 | test('apOrFunc internal', t => { 12 | t.ok(isFunction(apOrFunc), 'is a function') 13 | 14 | const f = sinon.spy() 15 | MockCrock.of = sinon.spy() 16 | 17 | const fn = apOrFunc(f) 18 | const rep = apOrFunc(MockCrock) 19 | 20 | t.ok(isFunction(fn), 'calling with a function returns a function') 21 | t.ok(isFunction(rep), 'calling with a TypeRep returns a function') 22 | 23 | fn('func') 24 | rep('typerep') 25 | 26 | t.ok(f.calledWith('func'), 'calls the function, passing the argument') 27 | t.ok(MockCrock.of.calledWith('typerep'), 'calls `of` on the TypeRep, passing the argument') 28 | 29 | // reset mock 30 | MockCrock.of = oldFn 31 | 32 | t.end() 33 | }) 34 | -------------------------------------------------------------------------------- /src/helpers/pipeK.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isChain = require('../core/isChain') 5 | const isFunction = require('../core/isFunction') 6 | 7 | const err = 'pipeK: Chain returning functions of the same type required' 8 | 9 | function pipeK(head, ...fns) { 10 | if(!(arguments.length && isFunction(head))) { 11 | throw new TypeError(err) 12 | } 13 | 14 | if(arguments.length === 1) { 15 | return head 16 | } 17 | 18 | const tail = fns.reduce((comp, fn) => { 19 | if(!isFunction(fn)) { 20 | throw new TypeError(err) 21 | } 22 | 23 | return function(m) { 24 | if(!isChain(m)) { 25 | throw new TypeError(err) 26 | } 27 | return comp(m).chain(fn) 28 | } 29 | }, x => x) 30 | 31 | return function() { 32 | return tail(head.apply(null, arguments)) 33 | } 34 | } 35 | 36 | module.exports = pipeK 37 | -------------------------------------------------------------------------------- /src/predicates/propEq.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Karthik Iyengar (karthikiyengar) */ 3 | 4 | const curry = require('../core/curry') 5 | const equals = require('../core/equals') 6 | const isDefined = require('../core/isDefined') 7 | const isEmpty = require('../core/isEmpty') 8 | const isInteger = require('../core/isInteger') 9 | const isNil = require('../core/isNil') 10 | const isString = require('../core/isString') 11 | 12 | // propEq: (String | Integer) -> a -> b -> Boolean 13 | function propEq(key, value, x) { 14 | if(!(isString(key) && !isEmpty(key) || isInteger(key))) { 15 | throw new TypeError( 16 | 'propEq: Non-empty String or Integer required for first argument' 17 | ) 18 | } 19 | 20 | if(isNil(x)) { 21 | return false 22 | } 23 | 24 | const target = x[key] 25 | 26 | return isDefined(target) && equals(target, value) 27 | } 28 | 29 | module.exports = curry(propEq) 30 | -------------------------------------------------------------------------------- /docs/src/partials/SocialButtons.soy: -------------------------------------------------------------------------------- 1 | {namespace SocialButtons} 2 | 3 | /** 4 | * @param page 5 | * @param siteUrl 6 | */ 7 | {template .render} 8 | 24 | {/template} 25 | -------------------------------------------------------------------------------- /src/helpers/composeS.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isSameType = require('../core/isSameType') 5 | const isSemigroupoid = require('../core/isSemigroupoid') 6 | 7 | const err = 'composeS: Semigroupoids of the same type required' 8 | 9 | /** composeS :: Semigroupoid s => (s y z, s x y, ..., s a b) -> s a z */ 10 | function composeS(...args) { 11 | if(!arguments.length) { 12 | throw new TypeError(err) 13 | } 14 | 15 | const ms = 16 | args.slice().reverse() 17 | 18 | const head = 19 | ms[0] 20 | 21 | if(!isSemigroupoid(head)) { 22 | throw new TypeError(err) 23 | } 24 | 25 | if(ms.length === 1) { 26 | return head 27 | } 28 | 29 | return ms.slice().reduce((comp, m) => { 30 | if(!isSameType(comp, m)) { 31 | throw new TypeError(err) 32 | } 33 | 34 | return comp.compose(m) 35 | }) 36 | } 37 | 38 | module.exports = composeS 39 | -------------------------------------------------------------------------------- /src/Maybe/maybeToArray.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Maybe = require('.') 5 | 6 | const curry = require('../core/curry') 7 | const isFunction = require('../core/isFunction') 8 | const isSameType = require('../core/isSameType') 9 | 10 | const applyTransform = maybe => 11 | maybe.either(() => [], x => [ x ]) 12 | 13 | const err = 14 | 'maybeToArray: Argument must be a Maybe instanstace or a Maybe returning function' 15 | 16 | function maybeToArray(maybe) { 17 | if(isFunction(maybe)) { 18 | return function(x) { 19 | const m = maybe(x) 20 | 21 | if(!isSameType(Maybe, m)) { 22 | throw new TypeError(err) 23 | } 24 | return applyTransform(m) 25 | } 26 | } 27 | 28 | if(isSameType(Maybe, maybe)) { 29 | return applyTransform(maybe) 30 | } 31 | 32 | throw new TypeError(err) 33 | } 34 | 35 | module.exports = curry(maybeToArray) 36 | -------------------------------------------------------------------------------- /src/helpers/defaultTo.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const defaultTo = require('./defaultTo') 4 | 5 | test('defaultTo', t => { 6 | const fn = 7 | defaultTo('def') 8 | 9 | const g = 10 | () => 'func' 11 | 12 | t.equal(fn(undefined), 'def', 'defaults an undefined value') 13 | t.equal(fn(null), 'def', 'defaults a null value') 14 | t.equal(fn(NaN), 'def', 'defaults a NaN value') 15 | t.equal(fn(0), 0, 'does not default a falsey number') 16 | t.equal(fn(1), 1, 'does not default a truthy number') 17 | t.equal(fn(''), '', 'does not default a falsey string') 18 | t.equal(fn('string'), 'string', 'does not default a truthy string') 19 | t.equal(fn(false), false, 'does not default a false') 20 | t.equal(fn(true), true, 'does not default a true') 21 | t.equal(fn(g)(), 'func', 'does not default a function') 22 | t.same(fn({}), {}, 'does not default an object') 23 | t.same(fn([]), [], 'does not default an array') 24 | 25 | t.end() 26 | }) 27 | 28 | -------------------------------------------------------------------------------- /src/pointfree/contramap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const compose = require('../core/compose') 5 | const curry = require('../core/curry') 6 | const isFunction = require('../core/isFunction') 7 | const isContravariant = require('../core/isContravariant') 8 | const fl = require('../core/flNames') 9 | 10 | /** contramap :: Functor f => (b -> a) -> f b -> f a */ 11 | function contramap(fn, m) { 12 | if(!isFunction(fn)) { 13 | throw new TypeError( 14 | 'contramap: Function required for first argument' 15 | ) 16 | } 17 | 18 | if(isFunction(m)) { 19 | return compose(m, fn) 20 | } 21 | 22 | if(isContravariant(m)) { 23 | return (m[fl.contramap] || m.contramap).call(m, fn) 24 | } 25 | 26 | throw new TypeError( 27 | 'contramap: Function or Contavariant Functor of the same type required for second argument' 28 | ) 29 | } 30 | 31 | module.exports = curry(contramap) 32 | -------------------------------------------------------------------------------- /src/pointfree/head.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const cloneIterable = require('../core/cloneIterable') 5 | const isArray = require('../core/isArray') 6 | const isFunction = require('../core/isFunction') 7 | const isIterable = require('../core/isIterable') 8 | const isString = require('../core/isString') 9 | 10 | const { Nothing, Just } = require('../core/Maybe') 11 | 12 | function head(m) { 13 | if(m && isFunction(m.head)) { 14 | return m.head() 15 | } 16 | 17 | if(isArray(m) || isString(m)) { 18 | return !m.length ? Nothing() : Just(m[0]) 19 | } 20 | 21 | if(isIterable(m)) { 22 | const cloned = cloneIterable(m) 23 | const iterator = cloned[Symbol.iterator]() 24 | const head = iterator.next() 25 | 26 | return head.done ? Nothing() : Just(head.value) 27 | } 28 | 29 | throw new TypeError('head: List or iterable required') 30 | } 31 | 32 | module.exports = head 33 | -------------------------------------------------------------------------------- /src/predicates/isTrue.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | 5 | const identity = x => x 6 | 7 | const isTrue = require('./isTrue') 8 | 9 | test('isTrue core', t => { 10 | t.ok(isFunction(isTrue)) 11 | 12 | t.equal(isTrue(undefined), false, 'returns false for undefined') 13 | t.equal(isTrue(null), false, 'returns false for null') 14 | t.equal(isTrue(0), false, 'returns false for falsey number') 15 | t.equal(isTrue(1), false, 'returns false for truthy number') 16 | t.equal(isTrue(false), false, 'returns false for false') 17 | t.equal(isTrue({}), false, 'returns false for an object') 18 | t.equal(isTrue([]), false, 'returns false for an array') 19 | t.equal(isTrue(identity), false, 'returns false for function') 20 | t.equal(isTrue(''), false, 'returns false for falsey string') 21 | t.equal(isTrue('string'), false, 'returns false for truthy string') 22 | 23 | t.equal(isTrue(true), true, 'returns true for true') 24 | 25 | t.end() 26 | }) 27 | -------------------------------------------------------------------------------- /src/helpers/liftA2.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const array = require('../core/array') 5 | const curry = require('../core/curry') 6 | const isApply = require('../core/isApply') 7 | const isArray = require('../core/isArray') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const map = array.map 12 | const ap = array.ap 13 | 14 | /** liftA2 :: Applicative m => (a -> b -> c) -> m a -> m b -> m c */ 15 | function liftA2(fn, x, y) { 16 | if(!isFunction(fn)) { 17 | throw new TypeError('liftA2: Function required for first argument') 18 | } 19 | 20 | if(!((isApply(x) || isArray(x)) && isSameType(x, y))) { 21 | throw new TypeError('liftA2: Applys of same type required for last two arguments') 22 | } 23 | 24 | if(isArray(x)) { 25 | return ap(y, map(fn, x)) 26 | } 27 | 28 | return x.map(fn).ap(y) 29 | } 30 | 31 | module.exports = curry(liftA2) 32 | -------------------------------------------------------------------------------- /src/helpers/mconcatMap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const _mconcatMap = require('../core/mconcatMap') 5 | const curry = require('../core/curry') 6 | const isFoldable = require('../core/isFoldable') 7 | const isFunction = require('../core/isFunction') 8 | const isMonoid = require('../core/isMonoid') 9 | 10 | /** mconcatMap :: Monoid M => M -> (b -> a) -> ([ b ] | List b) -> M a */ 11 | function mconcatMap(m, f, xs) { 12 | if(!isMonoid(m)) { 13 | throw new TypeError( 14 | 'mconcatMap: Monoid required for first argument' 15 | ) 16 | } 17 | 18 | if(!isFunction(f)) { 19 | throw new TypeError( 20 | 'mconcatMap: Function required for second argument' 21 | ) 22 | } 23 | 24 | if(!isFoldable(xs)) { 25 | throw new TypeError( 26 | 'mconcatMap: Foldable required for third argument' 27 | ) 28 | } 29 | 30 | return _mconcatMap(m, f, xs) 31 | } 32 | 33 | module.exports = curry(mconcatMap) 34 | -------------------------------------------------------------------------------- /src/predicates/isFalse.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | 5 | const identity = x => x 6 | 7 | const isFalse = require('./isFalse') 8 | 9 | test('isFalse core', t => { 10 | t.ok(isFunction(isFalse)) 11 | 12 | t.equal(isFalse(undefined), false, 'returns false for undefined') 13 | t.equal(isFalse(null), false, 'returns false for null') 14 | t.equal(isFalse(0), false, 'returns false for falsey number') 15 | t.equal(isFalse(1), false, 'returns false for truthy number') 16 | t.equal(isFalse(true), false, 'returns false for true') 17 | t.equal(isFalse({}), false, 'returns false for an object') 18 | t.equal(isFalse([]), false, 'returns false for an array') 19 | t.equal(isFalse(identity), false, 'returns false for function') 20 | t.equal(isFalse(''), false, 'returns false for falsey string') 21 | t.equal(isFalse('string'), false, 'returns false for truthy string') 22 | 23 | t.equal(isFalse(false), true, 'returns true for false') 24 | 25 | t.end() 26 | }) 27 | -------------------------------------------------------------------------------- /src/core/isString.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | 5 | const identity = x => x 6 | 7 | const isString = require('./isString') 8 | 9 | test('isString core', t => { 10 | t.ok(isFunction(isString)) 11 | 12 | t.equal(isString(undefined), false, 'returns false for undefined') 13 | t.equal(isString(null), false, 'returns false for null') 14 | t.equal(isString(0), false, 'returns false for falsey number') 15 | t.equal(isString(1), false, 'returns false for truthy number') 16 | t.equal(isString(false), false, 'returns false for false') 17 | t.equal(isString(true), false, 'returns false for true') 18 | t.equal(isString({}), false, 'returns false for an object') 19 | t.equal(isString([]), false, 'returns false for an array') 20 | t.equal(isString(identity), false, 'returns false for function') 21 | 22 | t.equal(isString(''), true, 'returns true for falsey string') 23 | t.equal(isString('string'), true, 'returns true for truthy string') 24 | 25 | t.end() 26 | }) 27 | -------------------------------------------------------------------------------- /src/helpers/mreduceMap.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFoldable = require('../core/isFoldable') 6 | const isFunction = require('../core/isFunction') 7 | const isMonoid = require('../core/isMonoid') 8 | const mconcatMap = require('../core/mconcatMap') 9 | 10 | /** mreduceMap :: Monoid M => M -> (b -> a) -> ( [ b ] | List b ) -> a */ 11 | function mreduceMap(m, f, xs) { 12 | if(!isMonoid(m)) { 13 | throw new TypeError( 14 | 'mreduceMap: Monoid required for first argument' 15 | ) 16 | } 17 | 18 | if(!isFunction(f)) { 19 | throw new TypeError( 20 | 'mreduceMap: Function required for second argument' 21 | ) 22 | } 23 | 24 | if(!isFoldable(xs)) { 25 | throw new TypeError( 26 | 'mreduceMap: Foldable required for third argument' 27 | ) 28 | } 29 | 30 | return mconcatMap(m, f, xs).valueOf() 31 | } 32 | 33 | module.exports = curry(mreduceMap) 34 | -------------------------------------------------------------------------------- /src/helpers/unary.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | const helpers = require('../test/helpers') 3 | 4 | const bindFunc = helpers.bindFunc 5 | 6 | const unary = require('./unary') 7 | 8 | test('unary helper', t => { 9 | const f = bindFunc(unary) 10 | 11 | const err = /unary: Argument must be a Function/ 12 | t.throws(f(undefined), err, 'throws with undefined') 13 | t.throws(f(null), err, 'throws with null') 14 | t.throws(f(0), err, 'throws with falsey number') 15 | t.throws(f(1), err, 'throws with truthy number') 16 | t.throws(f(''), err, 'throws with falsey string') 17 | t.throws(f('string'), err, 'throws with truthy string') 18 | t.throws(f(false), err, 'throws with false') 19 | t.throws(f(true), err, 'throws with true') 20 | t.throws(f({}), err, 'throws with object') 21 | t.throws(f([]), err, 'throws with array') 22 | const fn = unary((x, y, z) => ({ x: x, y: y, z: z })) 23 | 24 | t.same(fn(1, 2, 3), { x: 1, y: undefined, z: undefined }, 'only applies first argument to function') 25 | 26 | t.end() 27 | }) 28 | -------------------------------------------------------------------------------- /src/pointfree/filter.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | 6 | const isFunction = require('../core/isFunction') 7 | const isPredOrFunc = require('../core/isPredOrFunc') 8 | const isObject = require('../core/isObject') 9 | const object = require('../core/object') 10 | const predOrFunc = require('../core/predOrFunc') 11 | 12 | /** filter :: Filterable f => (a -> Boolean) -> f a -> f a */ 13 | function filter(pred, m) { 14 | if(!isPredOrFunc(pred)) { 15 | throw new TypeError('filter: Pred or predicate function required for first argument') 16 | } 17 | 18 | const fn = 19 | x => predOrFunc(pred, x) 20 | 21 | if(m && isFunction(m.filter)) { 22 | return m.filter(fn) 23 | } 24 | 25 | if(m && isObject(m)) { 26 | return object.filter(fn, m) 27 | } 28 | 29 | throw new TypeError('filter: Filterable or Object required for second argument') 30 | } 31 | 32 | module.exports = curry(filter) 33 | -------------------------------------------------------------------------------- /src/helpers/composeP.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | const isPromise = require('../core/isPromise') 6 | 7 | const err = 'composeP: Promise returning functions required' 8 | 9 | function applyPipe(f, g) { 10 | if(!isFunction(g)) { 11 | throw new TypeError(err) 12 | } 13 | 14 | return function() { 15 | const p = f.apply(null, arguments) 16 | 17 | if(!isPromise(p)) { 18 | throw new TypeError(err) 19 | } 20 | 21 | return p.then(g) 22 | } 23 | } 24 | 25 | function composeP(...args) { 26 | if(!arguments.length) { 27 | throw new TypeError(err) 28 | } 29 | 30 | const fns = 31 | args.reverse() 32 | 33 | const head = 34 | fns[0] 35 | 36 | if(!isFunction(head)) { 37 | throw new TypeError(err) 38 | } 39 | 40 | const tail = 41 | fns.slice(1).concat(x => x) 42 | 43 | return tail.reduce(applyPipe, head) 44 | } 45 | 46 | module.exports = composeP 47 | -------------------------------------------------------------------------------- /src/Maybe/lastToMaybe.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Last = require('../core/types').proxy('Last') 5 | 6 | const curry = require('../core/curry') 7 | const isFunction = require('../core/isFunction') 8 | const isSameType = require('../core/isSameType') 9 | 10 | const applyTransform = last => 11 | last.valueOf() 12 | 13 | /** lastToMaybe :: Last a -> Maybe a */ 14 | /** lastToMaybe :: (a -> Last b) -> a -> Maybe b */ 15 | function lastToMaybe(last) { 16 | if(isFunction(last)) { 17 | return function(x) { 18 | const m = last(x) 19 | 20 | if(!isSameType(Last, m)) { 21 | throw new TypeError('lastToMaybe: Last returning function required') 22 | } 23 | 24 | return applyTransform(m) 25 | } 26 | } 27 | 28 | if(isSameType(Last, last)) { 29 | return applyTransform(last) 30 | } 31 | 32 | throw new TypeError('lastToMaybe: Last or Last returning function required') 33 | } 34 | 35 | module.exports = curry(lastToMaybe) 36 | -------------------------------------------------------------------------------- /src/core/isArray.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | const unit = require('./_unit') 5 | 6 | const isArray = require('./isArray') 7 | 8 | test('isArray predicate function', t => { 9 | t.ok(isFunction(isArray), 'is a function') 10 | 11 | t.ok(isArray([]), 'returns true when passed an array') 12 | t.notOk(isArray(unit), 'returns false when passed a function') 13 | t.notOk(isArray(undefined), 'returns false when passed undefined') 14 | t.notOk(isArray(null), 'returns false when passed null') 15 | t.notOk(isArray(0), 'returns false when passed a falsey number') 16 | t.notOk(isArray(1), 'returns false when passed a truthy number') 17 | t.notOk(isArray(''), 'returns false when passed a falsey string') 18 | t.notOk(isArray('string'), 'returns false when passed a truthy string') 19 | t.notOk(isArray(false), 'returns false when passed false') 20 | t.notOk(isArray(true), 'returns false when passed true') 21 | t.notOk(isArray({}), 'returns false when passed an object') 22 | 23 | t.end() 24 | }) 25 | -------------------------------------------------------------------------------- /src/core/isObject.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | const unit = require('./_unit') 5 | 6 | const isObject = require('./isObject') 7 | 8 | test('isObject core', t => { 9 | t.ok(isFunction(isObject), 'is a function') 10 | 11 | t.equal(isObject(unit), false, 'returns false with function') 12 | t.equal(isObject(undefined), false, 'returns false with undefined') 13 | t.equal(isObject(null), false, 'returns false with null') 14 | t.equal(isObject(0), false, 'returns false with falsey number') 15 | t.equal(isObject(1), false, 'returns false with truthy number') 16 | t.equal(isObject(''), false, 'returns false with falsey string') 17 | t.equal(isObject('string'), false, 'returns false with truthy string') 18 | t.equal(isObject(false), false, 'returns false with false') 19 | t.equal(isObject(true), false, 'returns false with true') 20 | t.equal(isObject([]), false, 'returns false with an array') 21 | 22 | t.equal(isObject({}), true, 'returns true with an object') 23 | 24 | t.end() 25 | }) 26 | -------------------------------------------------------------------------------- /src/Pair/writerToPair.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFunction = require('../core/isFunction') 6 | 7 | const isWriter = 8 | x => !!x && isFunction(x.read) 9 | 10 | const applyTransform = w => 11 | w.read() 12 | 13 | /** writerToPair :: Monoid m => Writer m a -> Pair m a */ 14 | /** writerToPair :: Monoid m => (a -> Writer m a) -> Pair m b */ 15 | function writerToPair(writer) { 16 | if(isFunction(writer)) { 17 | return function(x) { 18 | const m = writer(x) 19 | 20 | if(!isWriter(m)) { 21 | throw new TypeError('writerToPair: Argument must be a Function that returns a Writer') 22 | } 23 | 24 | return applyTransform(m) 25 | } 26 | } 27 | 28 | if(isWriter(writer)) { 29 | return applyTransform(writer) 30 | } 31 | 32 | throw new TypeError('writerToPair: Argument must be a Writer or a Function that returns a Writer') 33 | } 34 | 35 | module.exports = curry(writerToPair) 36 | -------------------------------------------------------------------------------- /src/core/isDefined.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | const unit = require('./_unit') 5 | 6 | const isDefined = require('./isDefined') 7 | 8 | test('isDefined predicate function', t => { 9 | t.ok(isFunction(isDefined), 'is a function') 10 | 11 | t.equal(isDefined(unit), true, 'returns true with function') 12 | t.equal(isDefined(null), true, 'returns true with null') 13 | t.equal(isDefined(''), true, 'returns true with falsey string') 14 | t.equal(isDefined('string'), true, 'returns true with truthy string') 15 | t.equal(isDefined(0), true, 'returns true with falsey number') 16 | t.equal(isDefined(1), true, 'returns true with truthy number') 17 | t.equal(isDefined(false), true, 'returns true with false') 18 | t.equal(isDefined(true), true, 'returns true with true') 19 | t.equal(isDefined([]), true, 'returns true with an array') 20 | t.equal(isDefined({}), true, 'returns true with an object') 21 | 22 | t.equal(isDefined(undefined), false, 'returns false with undefined') 23 | 24 | t.end() 25 | }) 26 | -------------------------------------------------------------------------------- /src/helpers/liftA3.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const array = require('../core/array') 5 | const curry = require('../core/curry') 6 | const isApply = require('../core/isApply') 7 | const isArray = require('../core/isArray') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const map = array.map 12 | const ap = array.ap 13 | 14 | /** liftA3 :: Applicative m => (a -> b -> c -> d) -> m a -> m b -> m c -> m d */ 15 | function liftA3(fn, x, y, z) { 16 | if(!isFunction(fn)) { 17 | throw new TypeError('liftA3: Function required for first argument') 18 | } 19 | else if(!((isApply(x) || isArray(x)) && isSameType(x, y) && isSameType(x, z))) { 20 | throw new TypeError('liftA3: Applys of same type required for last three arguments') 21 | } 22 | 23 | if(isArray(x)) { 24 | return ap(z, ap(y, map(fn, x))) 25 | } 26 | 27 | return x.map(fn).ap(y).ap(z) 28 | } 29 | 30 | module.exports = curry(liftA3) 31 | -------------------------------------------------------------------------------- /src/core/isTypeRepOf.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | const unit = require('./_unit') 5 | 6 | const isTypeRepOf = require('./isTypeRepOf') 7 | 8 | test('isTypeRepOf internal', t => { 9 | t.ok(isFunction(isTypeRepOf), 'is a function') 10 | 11 | const fn = 12 | x => isTypeRepOf(String, x) 13 | 14 | t.notOk(fn(undefined), 'returns false for undefined value') 15 | t.notOk(fn(null), 'returns false for null value') 16 | t.notOk(fn(0), 'returns false for falsey number value') 17 | t.notOk(fn(1), 'returns false for truthy number value') 18 | t.notOk(fn(''), 'returns false for falsey string value') 19 | t.notOk(fn('string'), 'returns false for truthy string value') 20 | t.notOk(fn(false), 'returns false for false boolean value') 21 | t.notOk(fn(true), 'returns false for true boolean value') 22 | t.notOk(fn(unit), 'returns false for a function') 23 | t.notOk(fn(Array), 'returns false for different constructor') 24 | 25 | t.ok(fn(String), 'returns true for same constructor') 26 | 27 | t.end() 28 | }) 29 | -------------------------------------------------------------------------------- /src/helpers/once.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | const helpers = require('../test/helpers') 3 | 4 | const bindFunc = helpers.bindFunc 5 | 6 | const isFunction = require('../core/isFunction') 7 | const unit = require('../core/_unit') 8 | 9 | const once = require('./once') 10 | 11 | test('once helper', t => { 12 | const f = bindFunc(once) 13 | 14 | t.ok(isFunction(once), 'is a function') 15 | 16 | const err = /once: Argument must be a Function/ 17 | t.throws(f(undefined), err, 'throws with undefined') 18 | t.throws(f(null), err, 'throws with null') 19 | t.throws(f(0), err, 'throws with falsey number') 20 | t.throws(f(1), err, 'throws with truthy number') 21 | t.throws(f(''), err, 'throws with falsey string') 22 | t.throws(f('string'), err, 'throws with truthy string') 23 | t.throws(f(false), err, 'throws with false') 24 | t.throws(f(true), err, 'throws with true') 25 | t.throws(f({}), err, 'throws with an object') 26 | t.throws(f([]), err, 'throws with an array') 27 | 28 | t.doesNotThrow(f(unit), 'allows a function') 29 | 30 | t.end() 31 | }) 32 | -------------------------------------------------------------------------------- /src/helpers/pipeP.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isFunction = require('../core/isFunction') 5 | const isPromise = require('../core/isPromise') 6 | 7 | const err = 'pipeP: Promise returning functions required' 8 | 9 | function applyPipe(f, g) { 10 | if(!isFunction(g)) { 11 | throw new TypeError(err) 12 | } 13 | 14 | return function() { 15 | const p = f.apply(null, arguments) 16 | 17 | if(!isPromise(p)) { 18 | throw new TypeError(err) 19 | } 20 | 21 | return p.then(g) 22 | } 23 | } 24 | 25 | /** pipeP :: Promise p => ((a -> p b), (b -> p c), ..., (y -> p z)) -> a -> p z */ 26 | function pipeP(...fns) { 27 | if(!arguments.length) { 28 | throw new TypeError(err) 29 | } 30 | 31 | const head = 32 | fns[0] 33 | 34 | if(!isFunction(head)) { 35 | throw new TypeError(err) 36 | } 37 | 38 | const tail = 39 | fns.slice(1).concat(x => x) 40 | 41 | return tail.reduce(applyPipe, head) 42 | } 43 | 44 | module.exports = pipeP 45 | -------------------------------------------------------------------------------- /src/Maybe/firstToMaybe.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const First = require('../core/types').proxy('First') 5 | 6 | const curry = require('../core/curry') 7 | const isFunction = require('../core/isFunction') 8 | const isSameType = require('../core/isSameType') 9 | 10 | const applyTransform = first => 11 | first.valueOf() 12 | 13 | /** firstToMaybe :: First a -> Maybe a */ 14 | /** firstToMaybe :: (a -> First b) -> a -> Maybe b */ 15 | function firstToMaybe(first) { 16 | if(isFunction(first)) { 17 | return function(x) { 18 | const m = first(x) 19 | 20 | if(!isSameType(First, m)) { 21 | throw new TypeError('firstToMaybe: First returning function required') 22 | } 23 | 24 | return applyTransform(m) 25 | } 26 | } 27 | 28 | if(isSameType(First, first)) { 29 | return applyTransform(first) 30 | } 31 | 32 | throw new TypeError('firstToMaybe: First or First returning function required') 33 | } 34 | 35 | module.exports = curry(firstToMaybe) 36 | -------------------------------------------------------------------------------- /src/Maybe/getProp.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isDefined = require('../core/isDefined') 6 | const isEmpty = require('../core/isEmpty') 7 | const isNil = require('../core/isNil') 8 | const isInteger = require('../core/isInteger') 9 | const isString = require('../core/isString') 10 | const { Nothing, Just } = require('../core/Maybe') 11 | 12 | function fn(name) { 13 | function getProp(key, target) { 14 | if(!(isString(key) && !isEmpty(key) || isInteger(key))) { 15 | throw new TypeError(`${name}: Non-empty String or Integer required for first argument`) 16 | } 17 | 18 | if(isNil(target)) { 19 | return Nothing() 20 | } 21 | 22 | const value = target[key] 23 | 24 | return isDefined(value) 25 | ? Just(value) 26 | : Nothing() 27 | } 28 | 29 | return curry(getProp) 30 | } 31 | 32 | const getProp = 33 | fn('getProp') 34 | 35 | getProp.origFn = 36 | fn 37 | 38 | module.exports = getProp 39 | -------------------------------------------------------------------------------- /src/helpers/getPropOr.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Ian Hofmann-Hicks */ 3 | 4 | const curry = require('../core/curry') 5 | const isDefined = require('../core/isDefined') 6 | const isEmpty = require('../core/isEmpty') 7 | const isInteger = require('../core/isInteger') 8 | const isNil = require('../core/isNil') 9 | const isString = require('../core/isString') 10 | 11 | function fn(name) { 12 | function getPropOr(def, key, target) { 13 | if(!(isString(key) && !isEmpty(key) || isInteger(key))) { 14 | throw new TypeError(`${name}: Non-empty String or Integer required for second argument`) 15 | } 16 | 17 | if(isNil(target)) { 18 | return def 19 | } 20 | 21 | const value = target[key] 22 | 23 | return isDefined(value) 24 | ? value 25 | : def 26 | } 27 | 28 | return curry(getPropOr) 29 | } 30 | 31 | /** getPropOr :: a -> (String | Integer) -> b -> c */ 32 | const getPropOr = 33 | fn('getPropOr') 34 | 35 | getPropOr.origFn = 36 | fn 37 | 38 | module.exports = getPropOr 39 | -------------------------------------------------------------------------------- /src/helpers/pick.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isFoldable = require('../core/isFoldable') 6 | const isObject = require('../core/isObject') 7 | const isString = require('../core/isString') 8 | 9 | function pickKeys(obj) { 10 | return function(acc, key) { 11 | if(!isString(key)) { 12 | throw new TypeError('pick: Foldable of Strings is required for first argument') 13 | } 14 | return key && obj[key] !== undefined 15 | ? Object.assign(acc, { [key]: obj[key] }) 16 | : acc 17 | } 18 | } 19 | 20 | /** pick :: ([ String ] | List String) -> Object -> Object */ 21 | function pick(keys, obj) { 22 | if(!isFoldable(keys)) { 23 | throw new TypeError('pick: Foldable required for first argument') 24 | } 25 | else if(!isObject(obj)) { 26 | throw new TypeError('pick: Object required for second argument') 27 | } 28 | 29 | return keys.reduce(pickKeys(obj), {}) 30 | } 31 | 32 | module.exports = curry(pick) 33 | -------------------------------------------------------------------------------- /src/core/isNil.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | const unit = require('./_unit') 5 | 6 | const isNil = require('./isNil') 7 | 8 | test('isNil predicate function', t => { 9 | t.ok(isFunction(isNil), 'is a function') 10 | 11 | t.equal(isNil(unit), false, 'returns false with function') 12 | t.equal(isNil(0), false, 'returns false with falsey number') 13 | t.equal(isNil(1), false, 'returns false with truthy number') 14 | t.equal(isNil(''), false, 'returns false with falsey string') 15 | t.equal(isNil('string'), false, 'returns false with truthy string') 16 | t.equal(isNil(false), false, 'returns false with false') 17 | t.equal(isNil(true), false, 'returns false with true') 18 | t.equal(isNil([]), false, 'returns false with an array') 19 | t.equal(isNil({}), false, 'returns false with an object') 20 | 21 | t.equal(isNil(undefined), true, 'returns true with undefined') 22 | t.equal(isNil(null), true, 'returns true with null') 23 | t.equal(isNil(NaN), true, 'returns true with NaN') 24 | 25 | t.end() 26 | }) 27 | 28 | -------------------------------------------------------------------------------- /src/pointfree/traverse.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2016 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const array = require('../core/array') 5 | const curry = require('../core/curry') 6 | const isApplicative = require('../core/isApplicative') 7 | const isArray = require('../core/isArray') 8 | const isFunction = require('../core/isFunction') 9 | 10 | function traverse(af, fn, m) { 11 | if(!(isApplicative(af) || isFunction(af))) { 12 | throw new TypeError( 13 | 'traverse: Applicative TypeRep or Apply returning function required for first argument' 14 | ) 15 | } 16 | 17 | if(!isFunction(fn)) { 18 | throw new TypeError( 19 | 'traverse: Apply returning function required for second argument' 20 | ) 21 | } 22 | 23 | if(m && isFunction(m.traverse)) { 24 | return m.traverse(af, fn) 25 | } 26 | 27 | if(isArray(m)) { 28 | return array.traverse(af, fn, m) 29 | } 30 | 31 | throw new TypeError('traverse: Traversable or Array required for third argument') 32 | } 33 | 34 | module.exports = curry(traverse) 35 | -------------------------------------------------------------------------------- /src/core/isMap.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | const unit = require('./_unit') 5 | 6 | const isMap = require('./isMap') 7 | 8 | test('isMap predicate function', t => { 9 | t.ok(isFunction(isMap), 'is a function') 10 | 11 | t.ok(isMap(new Map()), 'returns true when passed a Map') 12 | t.notOk(isMap([]), 'returns false when passed an array') 13 | t.notOk(isMap(unit), 'returns false when passed a function') 14 | t.notOk(isMap(undefined), 'returns false when passed undefined') 15 | t.notOk(isMap(null), 'returns false when passed null') 16 | t.notOk(isMap(0), 'returns false when passed a falsey number') 17 | t.notOk(isMap(1), 'returns false when passed a truthy number') 18 | t.notOk(isMap(''), 'returns false when passed a falsey string') 19 | t.notOk(isMap('string'), 'returns false when passed a truthy string') 20 | t.notOk(isMap(false), 'returns false when passed false') 21 | t.notOk(isMap(true), 'returns false when passed true') 22 | t.notOk(isMap({}), 'returns false when passed an object') 23 | 24 | t.end() 25 | }) 26 | -------------------------------------------------------------------------------- /src/First/lastToFirst.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const First = require('.') 5 | const Last = require('../core/types').proxy('Last') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = last => 12 | First(last.valueOf()) 13 | 14 | /** lastToFirst :: Last a -> First a */ 15 | /** lastToFirst :: (a -> Last b) -> a -> First b */ 16 | function lastToFirst(last) { 17 | if(isFunction(last)) { 18 | return function(x) { 19 | const m = last(x) 20 | 21 | if(!isSameType(Last, m)) { 22 | throw new TypeError('lastToFirst: Last returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Last, last)) { 30 | return applyTransform(last) 31 | } 32 | 33 | throw new TypeError('lastToFirst: Last or Last returning function required') 34 | } 35 | 36 | module.exports = curry(lastToFirst) 37 | -------------------------------------------------------------------------------- /src/Last/maybeToLast.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Last = require('.') 5 | const Maybe = require('../core/types').proxy('Maybe') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = maybe => 12 | Last(maybe) 13 | 14 | /** maybeToLast :: Maybe a -> Last a */ 15 | /** maybeToLast :: (a -> Maybe b) -> a -> Last b */ 16 | function maybeToLast(maybe) { 17 | if(isFunction(maybe)) { 18 | return function(x) { 19 | const m = maybe(x) 20 | 21 | if(!isSameType(Maybe, m)) { 22 | throw new TypeError('maybeToLast: Maybe returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Maybe, maybe)) { 30 | return applyTransform(maybe) 31 | } 32 | 33 | throw new TypeError('maybeToLast: Maybe or Maybe returning function required') 34 | } 35 | 36 | module.exports = curry(maybeToLast) 37 | -------------------------------------------------------------------------------- /src/core/isDate.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | 5 | const identity = x => x 6 | 7 | const isDate = require('./isDate') 8 | 9 | test('isDate core', t => { 10 | t.ok(isFunction(isDate)) 11 | 12 | t.equal(isDate(undefined), false, 'returns false for undefined') 13 | t.equal(isDate(null), false, 'returns false for null') 14 | t.equal(isDate(0), false, 'returns false for falsey number') 15 | t.equal(isDate(1), false, 'returns false for truthy number') 16 | t.equal(isDate(false), false, 'returns false for false') 17 | t.equal(isDate(true), false, 'returns false for true') 18 | t.equal(isDate({}), false, 'returns false for an object') 19 | t.equal(isDate([]), false, 'returns false for an array') 20 | t.equal(isDate(identity), false, 'returns false for function') 21 | 22 | t.equal(isDate(new Date(undefined)), false, 'returns false for invalid date') 23 | 24 | t.equal(isDate(new Date()), true, 'returns true for new Date') 25 | t.equal(isDate(new Date('2018/12')), true, 'returns true from parsed date') 26 | 27 | t.end() 28 | }) 29 | -------------------------------------------------------------------------------- /src/predicates/isBoolean.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('../core/isFunction') 4 | const unit = require('../core/_unit') 5 | 6 | const isBoolean = require('./isBoolean') 7 | 8 | test('isBoolean predicate function', t => { 9 | t.ok(isFunction(isBoolean), 'is a function') 10 | 11 | t.equal(isBoolean(unit), false, 'returns false with function') 12 | t.equal(isBoolean(undefined), false, 'returns false with undefined') 13 | t.equal(isBoolean(null), false, 'returns false with null') 14 | t.equal(isBoolean(''), false, 'returns false with falsey string') 15 | t.equal(isBoolean('string'), false, 'returns false with truthy string') 16 | t.equal(isBoolean(0), false, 'returns false with falsey number') 17 | t.equal(isBoolean(1), false, 'returns false with truthy number') 18 | t.equal(isBoolean([]), false, 'returns false with an array') 19 | t.equal(isBoolean({}), false, 'returns false with an object') 20 | 21 | t.equal(isBoolean(false), true, 'returns true with false') 22 | t.equal(isBoolean(true), true, 'returns true with true') 23 | 24 | t.end() 25 | }) 26 | -------------------------------------------------------------------------------- /src/First/maybeToFirst.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const First = require('.') 5 | const Maybe = require('../core/types').proxy('Maybe') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = maybe => 12 | First(maybe) 13 | 14 | /** maybeToFirst :: Maybe a -> First a */ 15 | /** maybeToFirst :: (a -> Maybe b) -> a -> First b */ 16 | function maybeToFirst(maybe) { 17 | if(isFunction(maybe)) { 18 | return function(x) { 19 | const m = maybe(x) 20 | 21 | if(!isSameType(Maybe, m)) { 22 | throw new TypeError('maybeToFirst: Maybe returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Maybe, maybe)) { 30 | return applyTransform(maybe) 31 | } 32 | 33 | throw new TypeError('maybeToFirst: Maybe or Maybe returning function required') 34 | } 35 | 36 | module.exports = curry(maybeToFirst) 37 | -------------------------------------------------------------------------------- /src/Last/firstToLast.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Last = require('.') 5 | const First = require('../core/types').proxy('First') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = first => 12 | Last(first.valueOf()) 13 | 14 | /** firstToLast :: First a -> Last a */ 15 | /** firstToLast :: (a -> First b) -> a -> Last b */ 16 | function firstToLast(first) { 17 | if(isFunction(first)) { 18 | return function(x) { 19 | const m = first(x) 20 | 21 | if(!isSameType(First, m)) { 22 | throw new TypeError('firstToLast: First returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(First, first)) { 30 | return applyTransform(first) 31 | } 32 | 33 | throw new TypeError('firstToLast: First or First returning function required') 34 | } 35 | 36 | module.exports = curry(firstToLast) 37 | -------------------------------------------------------------------------------- /src/core/isNumber.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | const unit = require('./_unit') 5 | 6 | const isNumber = require('./isNumber') 7 | 8 | test('isNumber core', t => { 9 | t.ok(isFunction(isNumber), 'is a function') 10 | 11 | t.equal(isNumber(unit), false, 'returns false with function') 12 | t.equal(isNumber(undefined), false, 'returns false with undefined') 13 | t.equal(isNumber(null), false, 'returns false with null') 14 | t.equal(isNumber(''), false, 'returns false with falsey string') 15 | t.equal(isNumber('string'), false, 'returns false with truthy string') 16 | t.equal(isNumber(false), false, 'returns false with false') 17 | t.equal(isNumber(true), false, 'returns false with true') 18 | t.equal(isNumber([]), false, 'returns false with an array') 19 | t.equal(isNumber({}), false, 'returns false with an object') 20 | t.equal(isNumber(NaN), false, 'returns false with a NaN') 21 | 22 | t.equal(isNumber(0), true, 'returns true with falsey number') 23 | t.equal(isNumber(1), true, 'returns true with truthy number') 24 | 25 | t.end() 26 | }) 27 | -------------------------------------------------------------------------------- /src/helpers/fromPairs.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Pair = require('../core/types').proxy('Pair') 5 | 6 | const isFoldable = require('../core/isFoldable') 7 | const isSameType = require('../core/isSameType') 8 | const isString = require('../core/isString') 9 | 10 | function foldPairs(acc, pair) { 11 | if(!isSameType(Pair, pair)) { 12 | throw new TypeError('fromPairs: Foldable of Pairs required for argument') 13 | } 14 | 15 | const key = pair.fst() 16 | const value = pair.snd() 17 | 18 | if(!isString(key)) { 19 | throw new TypeError('fromPairs: String required for fst of every Pair') 20 | } 21 | 22 | return value !== undefined 23 | ? Object.assign(acc, { [key]: value }) 24 | : acc 25 | } 26 | 27 | /** fromPairs :: Foldable f => f (Pair String a) -> Object */ 28 | function fromPairs(xs) { 29 | if(!isFoldable(xs)) { 30 | throw new TypeError('fromPairs: Foldable of Pairs required for argument') 31 | } 32 | 33 | return xs.reduce(foldPairs, {}) 34 | } 35 | 36 | module.exports = fromPairs 37 | -------------------------------------------------------------------------------- /src/pointfree/valueOf.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | const sinon = require('sinon') 3 | 4 | const isFunction = require('../core/isFunction') 5 | const unit = require('../core/_unit') 6 | 7 | const constant = x => () => x 8 | 9 | const valueOf = require('./valueOf') 10 | 11 | test('valueOf pointfree', t => { 12 | const f = valueOf 13 | const x = 'result' 14 | const m = { valueOf: sinon.spy(constant(x)) } 15 | 16 | t.ok(isFunction(valueOf), 'is a function') 17 | 18 | t.equals(f(undefined), undefined, 'returns undefined for undefined') 19 | t.equals(f(null), null, 'returns null for null') 20 | t.equals(f('string'), 'string', 'returns the string for string') 21 | t.equals(f(false), false, 'returns the boolean for boolean') 22 | t.same(f([]), [], 'returns the array for array') 23 | t.same(f({}), {}, 'returns the object for object') 24 | t.equals(f(unit), unit, 'returns the function for function') 25 | 26 | const result = valueOf(m) 27 | 28 | t.ok(m.valueOf.called, 'calls value on the passed container') 29 | t.equal(result, x, 'returns the result of calling m.valueOf') 30 | 31 | t.end() 32 | }) 33 | -------------------------------------------------------------------------------- /src/core/isSymbol.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const isFunction = require('./isFunction') 4 | 5 | const identity = x => x 6 | 7 | const isSymbol = require('./isSymbol') 8 | 9 | test('isSymbol core', t => { 10 | t.ok(isFunction(isSymbol)) 11 | 12 | t.equal(isSymbol(undefined), false, 'returns false for undefined') 13 | t.equal(isSymbol(null), false, 'returns false for null') 14 | t.equal(isSymbol(0), false, 'returns false for falsey number') 15 | t.equal(isSymbol(1), false, 'returns false for truthy number') 16 | t.equal(isSymbol(false), false, 'returns false for false') 17 | t.equal(isSymbol(true), false, 'returns false for true') 18 | t.equal(isSymbol({}), false, 'returns false for an object') 19 | t.equal(isSymbol([]), false, 'returns false for an array') 20 | t.equal(isSymbol(identity), false, 'returns false for function') 21 | t.equal(isSymbol(Symbol), false, 'returns false for symbol constructor function') 22 | 23 | t.equal(isSymbol(Symbol()), true, 'returns true for empty symbol') 24 | t.equal(isSymbol(Symbol(42)), true, 'returns true for symbol with value') 25 | 26 | t.end() 27 | }) 28 | -------------------------------------------------------------------------------- /src/core/isFunction.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const unit = require('./_unit') 4 | 5 | const isFunction = require('./isFunction') 6 | 7 | test('isFunction core', t => { 8 | t.equal(typeof isFunction, 'function', 'is a function') 9 | 10 | t.equal(isFunction(unit), true, 'returns true when passed a function') 11 | t.equal(isFunction(undefined), false, 'returns false when passed undefined') 12 | t.equal(isFunction(null), false, 'returns false when passed null') 13 | t.equal(isFunction(0), false, 'returns false when passed a falsey number') 14 | t.equal(isFunction(1), false, 'returns false when passed a truthy number') 15 | t.equal(isFunction(''), false, 'returns false when passed a falsey string') 16 | t.equal(isFunction('string'), false, 'returns false when passed a truthy string') 17 | t.equal(isFunction(false), false, 'returns false when passed false') 18 | t.equal(isFunction(true), false, 'returns false when passed true') 19 | t.equal(isFunction([]), false, 'returns false when passed an array') 20 | t.equal(isFunction({}), false, 'returns false when passed an object') 21 | 22 | t.end() 23 | }) 24 | -------------------------------------------------------------------------------- /src/Last/eitherToLast.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Last = require('.') 5 | const Either = require('../core/types').proxy('Either') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = either => 12 | either.either(Last.empty, Last) 13 | 14 | /** eitherToLast :: Either b a -> Last a */ 15 | /** eitherToLast :: (a -> Either c b) -> a -> Last b */ 16 | function eitherToLast(either) { 17 | if(isFunction(either)) { 18 | return function(x) { 19 | const m = either(x) 20 | 21 | if(!isSameType(Either, m)) { 22 | throw new TypeError('eitherToLast: Either returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Either, either)) { 30 | return applyTransform(either) 31 | } 32 | 33 | throw new TypeError('eitherToLast: Either or Either returning function required') 34 | } 35 | 36 | module.exports = curry(eitherToLast) 37 | -------------------------------------------------------------------------------- /src/Last/resultToLast.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Last = require('.') 5 | const Result = require('../core/types').proxy('Result') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = result => 12 | result.either(Last.empty, Last) 13 | 14 | /** resultToLast :: Result b a -> Last a */ 15 | /** resultToLast :: (a -> Result c b) -> a -> Last b */ 16 | function resultToLast(result) { 17 | if(isFunction(result)) { 18 | return function(x) { 19 | const m = result(x) 20 | 21 | if(!isSameType(Result, m)) { 22 | throw new TypeError('resultToLast: Result returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Result, result)) { 30 | return applyTransform(result) 31 | } 32 | 33 | throw new TypeError('resultToLast: Result or Result returning function required') 34 | } 35 | 36 | module.exports = curry(resultToLast) 37 | -------------------------------------------------------------------------------- /src/Pair/fanout.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Pair = require('../core/Pair') 5 | 6 | const curry = require('../core/curry') 7 | const isContravariant = require('../core/isContravariant') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | const isSemigroupoid = require('../core/isSemigroupoid') 11 | 12 | const valid = (x, y) => 13 | isSameType(x, y) 14 | && isSemigroupoid(x) 15 | && isContravariant(x) 16 | && isFunction(x.first) 17 | && isFunction(x.second) 18 | 19 | /** fanout :: m a b -> m a c -> m a (b, c) */ 20 | function fanout(fst, snd) { 21 | if(isFunction(fst) && isFunction(snd)) { 22 | return x => 23 | Pair(fst(x), snd(x)) 24 | } 25 | 26 | if(valid(fst, snd)) { 27 | return fst.first() 28 | .compose(snd.second()) 29 | .contramap(x => Pair(x, x)) 30 | } 31 | 32 | throw new TypeError( 33 | 'fanout: Both arguments must be Arrows, Functions, or Stars of the same type' 34 | ) 35 | } 36 | 37 | module.exports = curry(fanout) 38 | -------------------------------------------------------------------------------- /src/helpers/binary.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | const helpers = require('../test/helpers') 3 | 4 | const bindFunc = helpers.bindFunc 5 | 6 | const binary = require('./binary') 7 | 8 | test('binary helper', t => { 9 | const f = bindFunc(binary) 10 | 11 | const err = /binary: Argument must be a Function/ 12 | t.throws(f(undefined), err, 'throws with undefined') 13 | t.throws(f(null), err, 'throws with null') 14 | t.throws(f(0), err, 'throws with falsey number') 15 | t.throws(f(1), err, 'throws with truthy number') 16 | t.throws(f(''), err, 'throws with falsey string') 17 | t.throws(f('string'), err, 'throws with truthy string') 18 | t.throws(f(false), err, 'throws with false') 19 | t.throws(f(true), err, 'throws with true') 20 | t.throws(f({}), err, 'throws with object') 21 | t.throws(f([]), err, 'throws with array') 22 | 23 | const fn = binary((x, y, z) => ({ x: x, y: y, z: z })) 24 | 25 | t.same(fn(1, 2, 3), { x: 1, y: 2, z: undefined }, 'only applies first two arguments to function') 26 | t.same(fn(true)(false), { x: true, y: false, z: undefined }, 'provides a curried function') 27 | 28 | t.end() 29 | }) 30 | -------------------------------------------------------------------------------- /src/First/eitherToFirst.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const First = require('.') 5 | const Either = require('../core/types').proxy('Either') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = either => 12 | either.either(First.empty, First) 13 | 14 | /** eitherToFirst :: Either b a -> First a */ 15 | /** eitherToFirst :: (a -> Either c b) -> a -> First b */ 16 | function eitherToFirst(either) { 17 | if(isFunction(either)) { 18 | return function(x) { 19 | const m = either(x) 20 | 21 | if(!isSameType(Either, m)) { 22 | throw new TypeError('eitherToFirst: Either returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Either, either)) { 30 | return applyTransform(either) 31 | } 32 | 33 | throw new TypeError('eitherToFirst: Either or Either returning function required') 34 | } 35 | 36 | module.exports = curry(eitherToFirst) 37 | -------------------------------------------------------------------------------- /src/First/resultToFirst.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const First = require('.') 5 | const Result = require('../core/types').proxy('Result') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = result => 12 | result.either(First.empty, First) 13 | 14 | /** resultToFirst :: Result b a -> First a */ 15 | /** resultToFirst :: (a -> Result c b) -> a -> First b */ 16 | function resultToFirst(result) { 17 | if(isFunction(result)) { 18 | return function(x) { 19 | const m = result(x) 20 | 21 | if(!isSameType(Result, m)) { 22 | throw new TypeError('resultToFirst: Result returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Result, result)) { 30 | return applyTransform(result) 31 | } 32 | 33 | throw new TypeError('resultToFirst: Result or Result returning function required') 34 | } 35 | 36 | module.exports = curry(resultToFirst) 37 | -------------------------------------------------------------------------------- /src/List/maybeToList.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const List = require('.') 5 | const Maybe = require('../core/types').proxy('Maybe') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = maybe => 12 | maybe.either( 13 | List.empty, 14 | List.of 15 | ) 16 | 17 | const err = 18 | 'maybeToList: Argument must be a Maybe instanstace or a Maybe returning function' 19 | 20 | /** maybeToList :: Maybe a -> List a */ 21 | /** maybeToList :: (a -> Maybe b) -> a -> List b */ 22 | function maybeToList(maybe) { 23 | if(isFunction(maybe)) { 24 | return function(x) { 25 | const m = maybe(x) 26 | 27 | if(!isSameType(Maybe, m)) { 28 | throw new TypeError(err) 29 | } 30 | 31 | return applyTransform(m) 32 | } 33 | } 34 | 35 | if(isSameType(Maybe, maybe)) { 36 | return applyTransform(maybe) 37 | } 38 | 39 | throw new TypeError(err) 40 | } 41 | 42 | module.exports = curry(maybeToList) 43 | 44 | -------------------------------------------------------------------------------- /src/Maybe/eitherToMaybe.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Maybe = require('.') 5 | const Either = require('../core/types').proxy('Either') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = either => 12 | either.either(Maybe.Nothing, Maybe.Just) 13 | 14 | /** eitherToMaybe :: Either b a -> Maybe a */ 15 | /** eitherToMaybe :: (a -> Either c b) -> a -> Maybe b */ 16 | function eitherToMaybe(either) { 17 | if(isFunction(either)) { 18 | return function(x) { 19 | const m = either(x) 20 | 21 | if(!isSameType(Either, m)) { 22 | throw new TypeError('eitherToMaybe: Either returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Either, either)) { 30 | return applyTransform(either) 31 | } 32 | 33 | throw new TypeError('eitherToMaybe: Either or Either returning function required') 34 | } 35 | 36 | module.exports = curry(eitherToMaybe) 37 | -------------------------------------------------------------------------------- /src/Maybe/resultToMaybe.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Maybe = require('.') 5 | const Result = require('../core/types').proxy('Result') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = result => 12 | result.either(Maybe.Nothing, Maybe.Just) 13 | 14 | /** resultToMaybe :: Result b a -> Maybe a */ 15 | /** resultToMaybe :: (a -> Result c b) -> a -> Maybe b */ 16 | function resultToMaybe(result) { 17 | if(isFunction(result)) { 18 | return function(x) { 19 | const m = result(x) 20 | 21 | if(!isSameType(Result, m)) { 22 | throw new TypeError('resultToMaybe: Result returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Result, result)) { 30 | return applyTransform(result) 31 | } 32 | 33 | throw new TypeError('resultToMaybe: Result or Result returning function required') 34 | } 35 | 36 | module.exports = curry(resultToMaybe) 37 | -------------------------------------------------------------------------------- /src/predicates/propSatisfies.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evilsoft) */ 3 | 4 | const curry = require('../core/curry') 5 | const isEmpty = require('../core/isEmpty') 6 | const isInteger = require('../core/isInteger') 7 | const isNil = require('../core/isNil') 8 | const isPredOrFunc = require('../core/isPredOrFunc') 9 | const isString = require('../core/isString') 10 | const predOrFunc = require('../core/predOrFunc') 11 | 12 | // propSatisfies: (String | Integer) -> (a -> Boolean) -> b -> Boolean 13 | // propSatisfies: (String | Integer) -> Pred a -> b -> Boolean 14 | function propSatisfies(key, pred, x) { 15 | if(!(isString(key) && !isEmpty(key) || isInteger(key))) { 16 | throw new TypeError( 17 | 'propSatisfies: Non-empty String or Integer required for first argument' 18 | ) 19 | } 20 | 21 | if(!isPredOrFunc(pred)) { 22 | throw new TypeError( 23 | 'propSatisfies: Pred or predicate function required for second argument' 24 | ) 25 | } 26 | 27 | return isNil(x) ? false : !!predOrFunc(pred, x[key]) 28 | } 29 | 30 | module.exports = curry(propSatisfies) 31 | -------------------------------------------------------------------------------- /src/Result/eitherToResult.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Result = require('.') 5 | const Either = require('../core/types').proxy('Either') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = either => 12 | either.either(Result.Err, Result.Ok) 13 | 14 | /** eitherToResult :: Either e a -> Result e a */ 15 | /** eitherToResult :: (a -> Either e b) -> a -> Result e b */ 16 | function eitherToResult(either) { 17 | if(isFunction(either)) { 18 | return function(x) { 19 | const m = either(x) 20 | 21 | if(!isSameType(Either, m)) { 22 | throw new TypeError('eitherToResult: Either returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Either, either)) { 30 | return applyTransform(either) 31 | } 32 | 33 | throw new TypeError('eitherToResult: Either or Either returning function required') 34 | } 35 | 36 | module.exports = curry(eitherToResult) 37 | -------------------------------------------------------------------------------- /src/Either/resultToEither.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Either = require('.') 5 | const Result = require('../core/types').proxy('Result') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = result => 12 | result.either(Either.Left, Either.Right) 13 | 14 | /** resultToEither :: Result e a -> Either e a */ 15 | /** resultToEither :: (a -> Result e b) -> a -> Either e b */ 16 | function resultToEither(result) { 17 | if(isFunction(result)) { 18 | return function(x) { 19 | const m = result(x) 20 | 21 | if(!isSameType(Result, m)) { 22 | throw new TypeError('resultToEither: Result returning function required') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Result, result)) { 30 | return applyTransform(result) 31 | } 32 | 33 | throw new TypeError('resultToEither: Result or Result returning function required') 34 | } 35 | 36 | module.exports = curry(resultToEither) 37 | -------------------------------------------------------------------------------- /src/pointfree/last.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2019 original and current authors */ 2 | /** @author RichardForrester */ 3 | 4 | const cloneIterable = require('../core/cloneIterable') 5 | const isArray = require('../core/isArray') 6 | const isFunction = require('../core/isFunction') 7 | const isIterable = require('../core/isIterable') 8 | const isString = require('../core/isString') 9 | 10 | const { Nothing, Just } = require('../core/Maybe') 11 | 12 | function last(m) { 13 | if (m && isFunction(m.last)) { 14 | return m.last() 15 | } 16 | 17 | if (isArray(m) || isString(m)) { 18 | return !m.length ? Nothing() : Just(m[m.length - 1]) 19 | } 20 | 21 | if (isIterable(m)) { 22 | const cloned = cloneIterable(m) 23 | const iterator = cloned[Symbol.iterator]() 24 | 25 | let curr = iterator.next() 26 | 27 | if (curr.done) { 28 | return Nothing() 29 | } 30 | 31 | let val 32 | while (!curr.done) { 33 | val = curr.value 34 | curr = iterator.next() 35 | } 36 | 37 | return Just(val) 38 | } 39 | 40 | throw new TypeError('last: Argument must be a List, String, or Iterable') 41 | } 42 | 43 | module.exports = last 44 | -------------------------------------------------------------------------------- /src/Maybe/find.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2018 original and current authors */ 2 | /** @author Dale Francis (dalefrancis88) */ 3 | 4 | const Pred = require('../core/types').proxy('Pred') 5 | 6 | const curry = require('../core/curry') 7 | const predOrFunc = require('../core/predOrFunc') 8 | const isFunction = require('../core/isFunction') 9 | const isFoldable = require('../core/isFoldable') 10 | const isSameType = require('../core/isSameType') 11 | 12 | const { Just, Nothing } = require('.') 13 | 14 | const accumulator = fn => (acc, cur) => 15 | !acc.found && predOrFunc(fn, cur) ? { found: true, value: cur } : acc 16 | 17 | /** find :: Foldable f => ((a -> Boolean) | Pred) -> f a -> Maybe a */ 18 | function find(fn, foldable) { 19 | if(!isFunction(fn) && !isSameType(Pred, fn)) { 20 | throw new TypeError('find: First argument must be a Pred or predicate') 21 | } 22 | 23 | if(!isFoldable(foldable)) { 24 | throw new TypeError('find: Second argument must be a Foldable') 25 | } 26 | 27 | const result = foldable.reduce(accumulator(fn), { found: false }) 28 | 29 | return result.found ? Just(result.value) : Nothing() 30 | } 31 | 32 | module.exports = curry(find) 33 | -------------------------------------------------------------------------------- /src/core/flNames.spec.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | const methods = require('./flNames') 4 | 5 | test('flMethods', t => { 6 | t.equals(methods.alt, 'fantasy-land/alt', 'provides alt') 7 | t.equals(methods.bimap, 'fantasy-land/bimap', 'provides bimap') 8 | t.equals(methods.chain, 'fantasy-land/chain', 'provides chain') 9 | t.equals(methods.compose, 'fantasy-land/compose', 'provides compose') 10 | t.equals(methods.concat, 'fantasy-land/concat', 'provides concat') 11 | t.equals(methods.contramap, 'fantasy-land/contramap', 'provides contramap') 12 | t.equals(methods.empty, 'fantasy-land/empty', 'provides empty') 13 | t.equals(methods.equals, 'fantasy-land/equals', 'provides equals') 14 | t.equals(methods.extend, 'fantasy-land/extend', 'provides extend') 15 | t.equals(methods.id, 'fantasy-land/id', 'provides id') 16 | t.equals(methods.map, 'fantasy-land/map', 'provides map') 17 | t.equals(methods.of, 'fantasy-land/of', 'provides of') 18 | t.equals(methods.promap, 'fantasy-land/promap', 'provides promap') 19 | t.equals(methods.reduce, 'fantasy-land/reduce', 'provides reduce') 20 | t.equals(methods.zero, 'fantasy-land/zero', 'provides zero') 21 | 22 | t.end() 23 | }) 24 | -------------------------------------------------------------------------------- /src/test/MockCrock.js: -------------------------------------------------------------------------------- 1 | const _implements = require('../core/implements') 2 | const _inspect = require('../core/inspect') 3 | const _equals = require('../core/equals') 4 | 5 | const constant = x => () => x 6 | 7 | const _type = constant('MockCrock') 8 | const typeString = 'crocks/MockCrock@1' 9 | const _of = x => MockCrock(x) 10 | 11 | function MockCrock(x) { 12 | const valueOf = constant(x) 13 | const map = fn => MockCrock(fn(x)) 14 | const type = _type 15 | const ap = m => m.map(x) 16 | const chain = fn => fn(x) 17 | const of = _of 18 | const sequence = () => x.map(MockCrock) 19 | const traverse = (_, f) => f(x).map(MockCrock) 20 | const inspect = () => `Mock${_inspect(x)}` 21 | const equals = 22 | m => _equals(m.valueOf(), x) 23 | 24 | return { 25 | valueOf, type, map, ap, 26 | chain, of, sequence, 27 | ['@@type']: typeString, 28 | traverse, inspect, equals 29 | } 30 | } 31 | 32 | MockCrock.of = _of 33 | MockCrock.type = _type 34 | MockCrock['@@type'] = typeString 35 | 36 | MockCrock['@@implements'] = _implements( 37 | [ 'ap', 'chain', 'equals', 'map', 'of', 'traverse' ] 38 | ) 39 | 40 | module.exports = MockCrock 41 | -------------------------------------------------------------------------------- /src/Async/resultToAsync.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Async = require('.') 5 | const Result = require('../core/types').proxy('Result') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = either => 12 | either.either(Async.Rejected, Async.Resolved) 13 | 14 | /** resultToAsync :: Result e a -> Async e a */ 15 | /** resultToAsync :: (a -> Result e b) -> a -> Async e b */ 16 | function resultToAsync(result) { 17 | if(isFunction(result)) { 18 | return function(x) { 19 | const m = result(x) 20 | 21 | if(!isSameType(Result, m)) { 22 | throw new TypeError('resultToAsync: Argument must be a Function that returns a Result') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Result, result)) { 30 | return applyTransform(result) 31 | } 32 | 33 | throw new TypeError('resultToAsync: Argument must be a Result or a Function that returns a Result') 34 | } 35 | 36 | module.exports = curry(resultToAsync) 37 | -------------------------------------------------------------------------------- /docs/src/styles/custom/_landing.scss: -------------------------------------------------------------------------------- 1 | .highlight-graphic { 2 | border-radius: 50%; 3 | text-align: center; 4 | margin-top: 50px; 5 | } 6 | 7 | // Highlights 8 | 9 | .highlight-graphic [class^="icon-16-"], 10 | .highlight-graphic [class*="icon-16-"] { 11 | box-shadow: 0 2px 8px rgba($primary, .2); 12 | border-radius: 50%; 13 | font-size: 62px; 14 | line-height: 137px; 15 | color: $accent; 16 | width: 140px; 17 | display: block; 18 | margin: auto; 19 | } 20 | 21 | @media (min-width: $screen-sm-min) { 22 | .highlight-graphic [class^="icon-16-"], 23 | .highlight-graphic [class*="icon-16-"] { 24 | font-size: 100px; 25 | line-height: 220px; 26 | width: 220px; 27 | } 28 | 29 | .highlight-graphic { 30 | margin-top: 0px; 31 | } 32 | } 33 | 34 | header.header { 35 | padding: 0 32px 16px; 36 | } 37 | 38 | article.about { 39 | padding: 64px 0px 32px; 40 | 41 | h3 { 42 | margin-top: 0; 43 | } 44 | } 45 | 46 | div.features { 47 | padding: 0; 48 | } 49 | 50 | .header-cta { 51 | a.btn { 52 | margin: 16px 0 0 0; 53 | } 54 | } 55 | 56 | .header-search { 57 | max-width: 450px; 58 | min-width: 33%; 59 | display: inline-block; 60 | margin-bottom: 16px; 61 | } -------------------------------------------------------------------------------- /src/Async/eitherToAsync.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const Async = require('.') 5 | const Either = require('../core/types').proxy('Either') 6 | 7 | const curry = require('../core/curry') 8 | const isFunction = require('../core/isFunction') 9 | const isSameType = require('../core/isSameType') 10 | 11 | const applyTransform = either => 12 | either.either(Async.Rejected, Async.Resolved) 13 | 14 | /** eitherToAsync :: Either e a -> Async e a */ 15 | /** eitherToAsync :: (a -> Either e b) -> a -> Async e b */ 16 | function eitherToAsync(either) { 17 | if(isFunction(either)) { 18 | return function(x) { 19 | const m = either(x) 20 | 21 | if(!isSameType(Either, m)) { 22 | throw new TypeError('eitherToAsync: Argument must be a Function that returns an Either') 23 | } 24 | 25 | return applyTransform(m) 26 | } 27 | } 28 | 29 | if(isSameType(Either, either)) { 30 | return applyTransform(either) 31 | } 32 | 33 | throw new TypeError('eitherToAsync: Argument must be an Either or a Function that returns an Either') 34 | } 35 | 36 | module.exports = curry(eitherToAsync) 37 | -------------------------------------------------------------------------------- /src/helpers/composeK.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const isChain = require('../core/isChain') 5 | const isFunction = require('../core/isFunction') 6 | 7 | const err = 'composeK: Chain returning functions of the same type required' 8 | 9 | /** composeK :: Chain m => ((y -> m z), (x -> m y), ..., (a -> m b)) -> a -> m z */ 10 | function composeK(...args) { 11 | if(!arguments.length) { 12 | throw new TypeError(err) 13 | } 14 | 15 | const fns = 16 | args.slice().reverse() 17 | 18 | const head = 19 | fns[0] 20 | 21 | if(!isFunction(head)) { 22 | throw new TypeError(err) 23 | } 24 | 25 | if(fns.length === 1) { 26 | return head 27 | } 28 | 29 | const tail = fns.slice(1).reduce((comp, fn) => { 30 | if(!isFunction(fn)) { 31 | throw new TypeError(err) 32 | } 33 | 34 | return function(m) { 35 | if(!isChain(m)) { 36 | throw new TypeError(err) 37 | } 38 | return comp(m).chain(fn) 39 | } 40 | }, x => x) 41 | 42 | return function() { 43 | return tail(head.apply(null, arguments)) 44 | } 45 | } 46 | 47 | module.exports = composeK 48 | -------------------------------------------------------------------------------- /src/pointfree/reject.js: -------------------------------------------------------------------------------- 1 | /** @license ISC License (c) copyright 2017 original and current authors */ 2 | /** @author Ian Hofmann-Hicks (evil) */ 3 | 4 | const curry = require('../core/curry') 5 | const isArray = require('../core/isArray') 6 | const isPredOrFunc = require('../core/isPredOrFunc') 7 | const isFunction = require('../core/isFunction') 8 | const isObject = require('../core/isObject') 9 | const object = require('../core/object') 10 | const predOrFunc = require('../core/predOrFunc') 11 | 12 | const not = 13 | fn => x => !fn(x) 14 | 15 | /** reject :: Foldable f => (a -> Boolean) -> f a -> f a */ 16 | function reject(pred, m) { 17 | if(!isPredOrFunc(pred)) { 18 | throw new TypeError( 19 | 'reject: Pred or predicate function required for first argument' 20 | ) 21 | } 22 | 23 | const fn = 24 | x => predOrFunc(pred, x) 25 | 26 | if(m && isFunction(m.reject)) { 27 | return m.reject(fn) 28 | } 29 | 30 | if(isArray(m)) { 31 | return m.filter(not(fn)) 32 | } 33 | 34 | if(isObject(m)) { 35 | return object.filter(not(fn), m) 36 | } 37 | 38 | throw new TypeError('reject: Foldable or Object required for second argument') 39 | } 40 | 41 | module.exports = curry(reject) 42 | --------------------------------------------------------------------------------