https://github.com/f0rr0/church-encoding
⛪ Church encodings for JavaScript primitives
https://github.com/f0rr0/church-encoding
church-encoding combinatory-logic functional-programming lambda-calculus
Last synced: about 1 month ago
JSON representation
⛪ Church encodings for JavaScript primitives
- Host: GitHub
- URL: https://github.com/f0rr0/church-encoding
- Owner: f0rr0
- License: wtfpl
- Created: 2018-04-01T00:25:49.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2020-06-02T18:13:02.000Z (over 5 years ago)
- Last Synced: 2025-08-30T00:38:40.654Z (about 1 month ago)
- Topics: church-encoding, combinatory-logic, functional-programming, lambda-calculus
- Language: JavaScript
- Homepage:
- Size: 1.82 MB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 19
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
![]()
Church encodings for JavaScript primitives
# church-encoding
[Wikipedia Page](https://en.wikipedia.org/wiki/Church_encoding). This is a thought exercise in functional programming to represent most of the javascript primitives using only lambdas (anonymous functions). It's not intended to be used in any production user facing software.## Motivation
I was informally introduced to this idea by watching [this talk](https://www.youtube.com/watch?v=XrNdvWqxBvA) by [John Hughes](http://www.cse.chalmers.se/~rjmh/) which is based on [his paper](https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf). [This talk](https://www.youtube.com/watch?v=IOiZatlZtGU) by [Philip Walder](http://homepages.inf.ed.ac.uk/wadler/) brilliantly explains this in a more historical context. The [SICP book](https://mitpress.mit.edu/sicp/full-text/book/book.html) also introduced me to using lambdas and recursive constructs to define operations on lists. There are many more comprehensive implementations in typed functional languages but I wanted to see how far I could go without a formal type system and combinators. Ultimately, on a more philosophical note, this exercise sufficiently proves that:
> Mathematics is not invented. It is discovered.
## Install
```
npm install @f0rr0/church-encoding@latest
```
or if you're using `yarn`
```
yarn add @f0rr0/church-encoding@latest
```## Usage
There are 3 different builds in `commonjs`, `umd` and `esmodule` format, should you have a preference or environment constraints. Normally, modern tools will automatically pick the `esmodule` build which enables tree-shaking.
```js
import {
cons,
emptyList,
zero,
inc,
map,
mul,
decodeInteger,
decodeList
} from '@f0rr0/church-encoding';const one = inc(zero);
const two = inc(one);
const list = cons(zero, cons(one, cons(two, emptyList)));console.log(decodeList(map(decodeInteger, list))); // [0, 1, 2]
const doubleList = map(i => mul(two, i), list);
console.log(decodeList(map(decodeInteger, doubleList))); // [0, 2, 4]
```
## APIThe API is organized into five parts which progressively build on each other. However, since everything is a function, they are not namespaced into separate exports. The function names pretty much sum up what they do.
1. [Boolean](#boolean)
2. [List](#list)
3. [Natural Number](#natural-number)
4. [Integer](#integer)
5. [Decode](#decode)### Boolean
* T
* F
* IF
* AND
* OR
* NOT### List
* emptyList
* cons
* head
* tail
* isEmpty
* map
* filter
* nth
* length### Natural Number
* zeroNat
* isZeroNat
* incNat
* decNat
* addNat
* subNat
* isEqualNat
* mulNat
* expNat
* isLessThanNat
* isLessThanEqualNat
* isGreaterThanNat
* isGreaterThanEqualNat
* divNat
* modNat### Integer
* pair
* first
* second
* zero
* isZero
* inc
* dec
* normalize
* abs
* negate
* add
* sub
* isEqual
* mul
* exp
* isNegative
* isLessThan
* isLessThanEqual
* isGreaterThan
* isGreaterThanEqual### Decode
* decodeBool
* decodeList
* decodeNat
* decodeInteger### Limitations
I still have to work on implementing rational numbers so that integer division can work. There are no `throw` or `Error` statements in the codebase since I strived to only use lambdas. Therefore, you need to be careful to not do mathematically impossible stuff e.g. divide a natural number by `zeroNat`, or else you'd be presented with a cryptic error.