@nathrach/early-birds
v1.0.3
Published
combinator birds for javascript
Downloads
8
Readme
early-birds
early-birds, like fantasy-birds, is a port of the haskell package Data.Aviary.Birds.
Install
npm i @nathrach/early-birds
Differences between early-birds and fantasy-birds
For many combinators, the behaviour of early-birds will (modulo bugs)
be identical to that of fantasy-birds. early-birds differs in that
intermediate results are eagerly evaluated, e.g. for the idstarstar bird,
(a -> b -> c) -> a -> b -> c
, idstarstar(f)(x)
will evalute f(x)
as
soon as x is provided. The intermediate results are also "closed over"
so that the evaluation occurs only once.
Consider the following example module which demonstrates the differences.
import { psi } from "../src/early-birds.mjs"
const F = require ("fantasy-birds")
const psiEarly = psi
const psiFantasy = F.psi
const toLower = string => (
console.log (`!---- evaluating "${string}".toLowerCase() ----!`),
string.toLowerCase()
)
const equal3 = x => y => x === y
const tests = [ 'true', 'True', 'TruE', 'false', 'False', 'FalsE' ]
// --- Using early-birds
console.log ('\n !#### Testing with psiEarly ####!\n')
const isTrueEarly = psiEarly (equal3) (toLower) ('TRUE')
tests.map (e => console.log (`Testing isTrueEarly ("${e}"): ${isTrueEarly (e)}\n`))
// --- Using fantasy-birds
console.log ('\n!#### Testing with psiFantasy ####!\n')
const isTrueFantasy = psiFantasy (equal3) (toLower) ('TRUE')
tests.map (e => console.log (`Testing isTrue ("${e}"): ${isTrueFantasy (e)}\n`))
When this module is imported into node.js the following is output:
> await import ('./examples/sameLetters.mjs')
!#### Testing with psiEarly ####!
!---- evaluating "TRUE".toLowerCase() ----!
!---- evaluating "true".toLowerCase() ----!
Testing isTrueEarly ("true"): true
!---- evaluating "True".toLowerCase() ----!
Testing isTrueEarly ("True"): true
!---- evaluating "TruE".toLowerCase() ----!
Testing isTrueEarly ("TruE"): true
!---- evaluating "false".toLowerCase() ----!
Testing isTrueEarly ("false"): false
!---- evaluating "False".toLowerCase() ----!
Testing isTrueEarly ("False"): false
!---- evaluating "FalsE".toLowerCase() ----!
Testing isTrueEarly ("FalsE"): false
!#### Testing with psiFantasy ####!
!---- evaluating "TRUE".toLowerCase() ----!
!---- evaluating "true".toLowerCase() ----!
Testing isTrue ("true"): true
!---- evaluating "TRUE".toLowerCase() ----!
!---- evaluating "True".toLowerCase() ----!
Testing isTrue ("True"): true
!---- evaluating "TRUE".toLowerCase() ----!
!---- evaluating "TruE".toLowerCase() ----!
Testing isTrue ("TruE"): true
!---- evaluating "TRUE".toLowerCase() ----!
!---- evaluating "false".toLowerCase() ----!
Testing isTrue ("false"): false
!---- evaluating "TRUE".toLowerCase() ----!
!---- evaluating "False".toLowerCase() ----!
Testing isTrue ("False"): false
!---- evaluating "TRUE".toLowerCase() ----!
!---- evaluating "FalsE".toLowerCase() ----!
Testing isTrue ("FalsE"): false
[Module: null prototype] { }
>
In the example, "TRUE".toLowerCase
is evaluted only once for the
early-birds psi and is evaluted for each test for the fantasy-birds psi.
The eager closure can be useful when applying the combinators to pure
functions since the evaluation will always be the same. However, for
applications that rely on the side effects, the fantasy-birds behaviour
is likely what is desired.
The Aviary
applicator :: (a -> b) -> a -> b
- I* combinator
- λ abstraction:
λab.ab
becard :: (c -> d) -> (b -> c) -> (a -> b) -> a -> d
- B3 combinator
- λ abstraction:
λabcd.a(b(cd))
blackbird :: (c -> d) -> (a -> b -> c) -> a -> b -> d
- B1 combinator
- λ abstraction:
λabcd.a(bcd)
bluebird :: (b -> c) -> (a -> b) -> a -> c
- B combinator
- λ abstraction:
λabc.a(bc)
bluebird_ :: (a -> c -> d) -> a -> (b -> c) -> b -> d
- B' combinator
- λ abstraction:
λabcd.ab(cd)
bunting :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
- B2 combinator
- λ abstraction:
λabcde.a(bcde)
cardinal :: (a -> b -> c) -> b -> a -> c
- C combinator
- λ abstraction:
λabc.acb
cardinal_ :: (c -> a -> d) -> (b -> c) -> a -> b -> d
- C' combinator
- λ abstraction:
λabcd.a(bd)c
cardinalstar :: (a -> c -> b -> d) -> a -> b -> c -> d
- C* combinator
- λ abstraction:
λabcd.abdc
cardinalstarstar :: (a -> b -> d -> c -> e) -> a -> b -> c -> d -> e
- C** combinator
- λ abstraction:
λabcde.abced
dickcissel :: (a -> b -> d -> e) -> a -> b -> (c -> d) -> c -> e
- D1 combinator
- λ abstraction:
λabcde.abc(de)
dove :: (a -> c -> d) -> a -> (b -> c) -> b -> d
- D combinator
- λ abstraction:
λabcd.ab(cd)
dovekie :: (c -> d -> e) -> (a -> c) -> a -> (b -> d) -> b -> e
- D2 combinator
- λ abstraction:
λabcde.a(bc)(de)
eagle :: (a -> d -> e) -> a -> (b -> c -> d) -> b -> c -> e
- E combinator
- λ abstraction:
λabcde.ab(cde)
eaglebald :: (e -> f -> g) -> (a -> b -> e) -> a -> b -> (c -> d -> f) -> c -> d -> g
- E^ combinator
- λ abstraction:
λabcdefg.a(bcd)(efg)
finch :: a -> b -> (b -> a -> c) -> c
- F combinator
- λ abstraction:
λabc.cba
finchstar :: (c -> b -> a -> d) -> a -> b -> c -> d
- F* combinator
- λ abstraction:
λabcd.adcb
finchstarstar :: (a -> d -> c -> b -> e) -> a -> b -> c -> d -> e
- F** combinator
- λ abstraction:
λabcde.abedc
goldfinch :: (b -> c -> d) -> (a -> c) -> a -> b -> d
- G combinator
- λ abstraction:
λabcd.ad(bc)
hummingbird :: (a -> b -> a -> c) -> a -> b -> c
- H combinator
- λ abstraction:
λabc.abcb
idiot :: a -> a
- I combinator
- λ abstraction:
λa.a
idstar :: (a -> b) -> a -> b
- I* combinator
- λ abstraction:
λab.ab
idstarstar :: (a -> b -> c) -> a -> b -> c
- I** combinator
- λ abstraction:
λabc.abc
jalt :: (a -> c) -> a -> b -> c
- jalt combinator
- λ abstraction:
λabc.ab
jalt_ :: (a -> b -> d) -> a -> b -> c -> d
- jalt' combinator
- λ abstraction:
λabcd.abc
jay :: (a -> b -> b) -> a -> b -> a -> b
- J combinator
- λ abstraction:
λabcd.ab(adc)
kestrel :: a -> b -> a
- K combinator
- λ abstraction:
λab.a
kite :: a -> b -> b
- Ki combinator
- λ abstraction:
λab.b
owl :: ((a -> b) -> a) -> (a -> b) -> b
- O combinator
- λ abstraction:
λab.b(ab)
phoenix :: (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d
S' combinator
λ abstraction:
λabcd.a(bd)(cd)
same as
starling_
psi :: (b -> b -> c) -> (a -> b) -> a -> a -> c
- Psi combinator
- λ abstraction:
λabcd.a(bc)(bd)
quacky :: a -> (a -> b) -> (b -> c) -> c
- Q4 combinator
- λ abstraction:
λabc.c(ba)
queer :: (a -> b) -> (b -> c) -> a -> c
- Q combinator
- λ abstraction:
λabc.b(ac)
quirky :: (a -> b) -> a -> (b -> c) -> c
- Q3 combinator
- λ abstraction:
λabc.c(ab)
quixotic :: (b -> c) -> a -> (a -> b) -> c
- Q1 combinator
- λ abstraction:
λabc.a(cb)
quizzical :: a -> (b -> c) -> (a -> b) -> c
- Q2 combinator
- λ abstraction:
λabc.b(ca)
robin :: a -> (b -> a -> c) -> b -> c
- R combinator
- λ abstraction:
λabc.bca
robinstar :: (b -> c -> a -> d) -> a -> b -> c -> d
- R* combinator
- λ abstraction:
λabcd.acdb
robinstarstar :: (a -> c -> d -> b -> e) -> a -> b -> c -> d -> e
- R** combinator
- λ abstraction:
λabcde.abdec
starling :: (a -> b -> c) -> (a -> b) -> a -> c
- S combinator
- λ abstraction:
λabc.ac(bc)
starling_ :: (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d
S' combinator
λ abstraction:
λabcd.a(bd)(cd)
same as
phoenix
thrush :: a -> (a -> b) -> b
- T combinator
- λ abstraction:
λab.ba
vireo :: a -> b -> (a -> b -> c) -> c
- V combinator
- λ abstraction:
λabc.cab
vireostar :: (b -> a -> b -> d) -> a -> b -> b -> d
- V* combinator
- λ abstraction:
λabcd.acbd
vireostarstar :: (a -> c -> b -> c -> e) -> a -> b -> c -> c -> e
- V** combinator
- λ abstraction:
λabcde.abecd
warbler :: (a -> a -> b) -> a -> b
- W combinator
- λ abstraction:
λab.abb
warbler1 :: a -> (a -> a -> b) -> b
- W1 combinator
- λ abstraction:
λab.baa
warblerstar :: (a -> b -> b -> c) -> a -> b -> c
- W* combinator
- λ abstraction:
λabc.abcc
warblerstarstar :: (a -> b -> c -> c -> d) -> a -> b -> c -> d
- W** combinator
- λ abstraction:
λabcd.abcdd