{"id":17920599,"url":"https://github.com/nem035/js-function-fun-2","last_synced_at":"2025-06-30T13:40:10.171Z","repository":{"id":92965960,"uuid":"68516133","full_name":"nem035/js-function-fun-2","owner":"nem035","description":"Fun with functional programming in JavaScript (2)","archived":false,"fork":false,"pushed_at":"2016-09-27T16:49:12.000Z","size":54,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-08T22:12:48.015Z","etag":null,"topics":["composition","functional-programming","functor","javascript","monad","monoid","semigroup"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nem035.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-18T11:06:09.000Z","updated_at":"2018-12-28T04:06:04.000Z","dependencies_parsed_at":"2023-04-12T11:24:45.685Z","dependency_job_id":null,"html_url":"https://github.com/nem035/js-function-fun-2","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nem035%2Fjs-function-fun-2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nem035%2Fjs-function-fun-2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nem035%2Fjs-function-fun-2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nem035%2Fjs-function-fun-2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nem035","download_url":"https://codeload.github.com/nem035/js-function-fun-2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246966022,"owners_count":20861985,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["composition","functional-programming","functor","javascript","monad","monoid","semigroup"],"created_at":"2024-10-28T20:26:17.184Z","updated_at":"2025-04-03T08:32:34.121Z","avatar_url":"https://github.com/nem035.png","language":"JavaScript","readme":"# JS-Function-Fun-2\n\nFun with functional programming in JS.\n\nContinuation of [js-function-fun](https://github.com/nem035/js-function-fun)\n\n## Libraries used\n\n  - [BaconJS](https://baconjs.github.io/)\n  - [Data.Either](https://github.com/folktale/data.either)\n  - [Data.Future](https://github.com/folktale/data.future)\n  - [PointFree Fantasy](https://github.com/DrBoolean/pointfree-fantasy)\n  - [Ramda](http://ramdajs.com/)\n\n## Definitions\n\n- Functor is any data type (Container) that defines how `map()` applies to it.\n\n- Monad is a (Pointed) Functor that defines how `of()`, `mjoin()` and `chain()` apply to it\n\n- Applicative is a (Applied) Pointed Functor that defines how `ap()` applies to it\n\n- Semigroup is any data type (Container) that defines how `concat()` applies to it\n\n- Monoid is a Semigroup that defines how `empty()` applies to it.\n\n## PointFree methods\n\n- [map](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L806)\n\n  ```js\n  map = curry( (f, u) =\u003e u.map(f) )\n\n  // Where u is a Functor with a map() defined as\n  u.map = (f) =\u003e new u(f(this.value))\n\n  // map takes a Function and a Functor and returns a new Functor\n  // map:: (a -\u003e b) -\u003e fa -\u003e fb\n\n  // example\n  map add(3) Functor(2) // Functor(5)\n\n  // map() essentially unwraps a value from the Functor context,\n  // applies the passed in Function to that value,\n  // and rewraps it back in the Functor context\n\n  // Laws\n\n  // identity\n  map(id) == id\n\n  // composition\n  compose(map(f), map(g)) == map(compose(f, g))\n  ```\n\n- [compose](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L780)\n\n  ```js\n  compose = curry( (f, g, x) =\u003e f(g(x)) )\n\n  // compose :: (b -\u003e c) -\u003e (a -\u003e b) -\u003e (a -\u003e c)\n\n  // compose() essentially performs a RTL pipe of functions,\n  // passing the output of the current function as the input of the next function\n\n  // example\n  compose add(3) multiply(5) 2 // 2 * 5 + 3\n\n  // compose() is powerful when combined with map\n  map(compose(first, reverse), Container(\"dog\")) // \"g\"\n\n  // Laws\n\n  // left identity\n  compose(id, f) == f\n\n  // right identity\n  compose(f, id) == f\n\n  // associativity\n  compose(compose(f, g), h) == compose(f, compose(g, h))\n\n  ```\n\n- [of](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L842)\n\n  ```js\n  of = (x) =\u003e x.of\n\n  Array.of(1, 2) // [1, 2]\n  ```\n\n- [mjoin](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L826)\n\n  ```js\n  mjoin = (mmv) =\u003e chain(id, mmv)\n\n  // mjoin :: M M a -\u003e M a\n\n  // example\n  compose(map(map(add(3))), Container(Container))(2) // Container(5)\n  // is the same as\n  compose(mjoin, add(3), Container(Container))(2) // Container(5)\n  ```\n\n- [chain](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L822)\n\n  ```js\n  chain = curry( (f, mv) =\u003e mv.chain(f) )\n\n  // chain :: (a -\u003e M b) -\u003e M a -\u003e M b\n\n  // Where mv is a Functor with a chain() defined as\n  mv.chain = (f) =\u003e f(this.value)\n\n  // we can think of chain as a composition of mjoin() and map()\n  chain = (f) =\u003e compose(mjoin, map(f)) // flattens out the map\n\n  // example\n  compose(map(map(log), Container(Container))(2) // logs '2'\n  // is the same as\n  compose(mjoin, log, Container(Container))(2) // logs '2'\n  ```\n\n- [ap](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L810)\n\n  ```js\n  ap = curry( (a1, a2) =\u003e a1.ap(a2) )\n\n  // ap :: A (a -\u003e b) -\u003e A a -\u003e A b\n\n  // example\n  Container.of(f).ap(Container(x)).ap(Container(y))   // Container(f(x, y))\n  Container.of(add).ap(Container(1)).ap(Container(3)) // Container(4)\n\n  // Laws\n\n  // identity\n  A(id).ap(m) == m\n\n  // composition\n  A(compose).ap(f).ap(g).ap(w) == f.ap(g.ap(w)))\n\n  // homomorphism\n  A(f).ap(A(x)) == A(f(x))\n\n  // interchange\n  u.ap(A(y)) == A((f) =\u003e f(y)).ap(u)\n  ```\n\n- [liftA2](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L814)\n\n  ```js\n  liftA2 = curry( (f, x, y) =\u003e map(f,x).ap(y) )\n\n  // where map(f,x) returns a Functor with an ap() method defined as\n  u.ap = (b) =\u003e new u(this.value(b.value))\n\n  // example\n  Maybe.of(save).ap(getVal('#email')).ap(getVal('#password'))\n  // is the same as\n  liftA2(save, getVal('#email'), getVal('#password'))\n  ```\n\n- empty\n\n  ```js\n    // returns a default \"empty\" value for the type\n    Array.empty()    // []\n    String.empty()   // ''\n  ```\n\n- [concat](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L830)\n\n  ```js\n  concat = (x, y) =\u003e x.concat(y)\n\n  // example\n  concat([1, 2], [3, 4]) // [1, 2, 3, 4]\n\n  // Laws\n\n  // left identity\n  concat(empty, x) == x\n\n  // right identity\n  concat(x, empty) == x\n\n  // associativity\n  concat(concat(x, y), z) == concat(x, concat(y, z))\n  ```\n\n- [mconcat](https://github.com/DrBoolean/pointfree-fantasy/blob/master/dist/pointfree.amd.js#L834)\n\n  ```js\n  mconcat = (xs, empty) =\u003e xs.length ? xs.reduce(concat) : empty()\n\n  // example\n  mconcat([toUpperCase, reverse])(['stuff']) // STUFFffuts\n\n  // validation example\n  const checkValidations = mconcat([checkPassword, checkEmail, checkUsername]);\n  checkValidations({ name: 'Bob' }) // ['missing password', 'missing email']\n  ```\n\n## Running the exercises\n\n    node app\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnem035%2Fjs-function-fun-2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnem035%2Fjs-function-fun-2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnem035%2Fjs-function-fun-2/lists"}