Implements Fantasy Land:
Functor, Bifunctor,
Apply, Applicative, Chain,
Monad
This data structure is a wrapper for reuse everyday mutable and effectfull promise based libs in a functional monadic future based fashion.
If Fluture moand wraps a computation that async resolve to a value, Futurity brigs tree data structures:
-
Reader e -> a : Reader monad used to lazy wrap a mutable effectfull lib (like knex or superagent for example).
Is a lazy Product Type that enables the composition of computations that depend on a shared > environment (e -> a). The left portion, the e must be fixed to a type for all related computations. The right portion a can vary in its type. -- Crocks Dev
-
e -> e : Environment reducer function, used to transforms environment before run it in the computation Reader.
-
Reader a -> Future b : A lazy structure (another Reader Monad) that takes the result value of the collapsing of first reader monad as environment and return a Future instance. All fluture operators (map, chain, ap...) applied to the data structure transforms the yet to exists future instace wrapped by the this monad.
Futurity is implemented in a few lines of code that mix up some good libraries:
- Add Futurity to your project
yarn add futurity
-
If not already in your project add peer dependencies
yarn add fluture
You can look in tests for other examples.
Sample of knex wrapping.
import Knex from 'knex'
import { Futurity, coMap, envMap } from 'futurity'
import * as F from 'fluture'
const I = a => a
const pipe = (...args) => args.reduce((f, g) => x => g(f(x)))
const db = Knex({
client: 'sqlite3',
connection: {
filename: 'tests/chinook.sqlite'
},
useNullAsDefault: true
})
// Futurity that wrap knex instance
const DbFuturity = (db, args) =>
Futurity.lift(
p => db(...args),
qb => F.attemptP(() => qb)
)
const query = pipe(
coMap(qb => qb.where({ Composer: 'Nirvana' })),
coMap(qb => qb.limit(2)),
F.map(rows => rows.map(track => track.Name))
)(DbFuturity(db, ['Track']))
(async function(){
const value = await F.promise(query)
console.log(value)
})()
Output:
['Aneurysm', 'Smells Like Teen Spirit']
Sample of superagent wrapping
import request from 'superagent'
import { Futurity, coMap, envMap } from 'futurity'
import * as F from 'fluture'
const I = a => a
const pipe = (...args) => args.reduce((f, g) => x => g(f(x)))
// Futurity that wrap Superagent instance
const SaFuturity = method =>
Futurity.lift(request[method], agent => F.attemptP(() => agent))
const query = pipe(
envMap(() => 'https://jsonplaceholder.typicode.com/todos/1'),
F.map(res => res.body),
F.map(body => body.title),
coMap(req => req.set('accept', 'json'))
)(SaFuturity('get'))
(async function(){
const title = await F.promise(query)
console.log(title)
})()
Output:
'delectus aut autem'
The data structure is a Fluture extension (so you can directly use all Fluture operators and API).
Exception for cache and hooks not yet implemented (but you can collapse a Futurity instance to a Fluture instance at you occorence).
In addition to standard Fluture functions we have:
Contruct a new Futurity Instance, environment is intialized to identity function.
-
computation: e -> a
Function that takes the environment and return the target value. -
computationToFuture: a -> Future b
Function that takes the computation result and transform it to a future.
Returns: Futurity Instance
Environment reducer. Function to transform the initial environment.
pred: e -> e
Function that has the current environment as input and return the new environment.
Returns: Futurity Instance
Function to transform the wrapped effectfull object.
(a, e) -> a
For your confort the environment is passed as second argumet so you can you it.
Returns: Futurity Instance
Make the futurity instance collapse to a Future instance (not yet resolved).
fty
Futurity instance.
Returns: Future Instance
Distributed under the MIT License. See LICENSE
for more information.
Fabiano Taioli - ftaioli@gmail.com
Project Link: https://github.com/FbN/futurity