Skip to content

Instantly share code, notes, and snippets.

@i-am-tom
i-am-tom / interactive-config.js
Last active November 1, 2018 09:06
Prompt users for missing/sensitive config data as and when it's required.
// Sometimes, you might want to supply *some* config, but
// not necessarily *all*. Maybe your password is really
// secret, so you don't want to risk saving it in a config
// file. In which case, you'll want to ask the user to enter
// it when your script runs.
// This interface provides a flexible approach, where
// the user is prompted for a missing key when it's
// requested - if a particular key isn't needed for a given
// run, the user won't need to enter it. Of course, if the
@i-am-tom
i-am-tom / Lazy.js
Last active January 13, 2024 01:35
A Fantasy Land-compliant type for lazy computation.
const fl = require('fantasy-land')
//- Lazy holds a vaue in a thunk, effectively delaying
//- evaluation until required. This is useful when we're
//- in a situation with either very large data set or
//- cyclical data.
//@ make stack-safe.
//> type Lazy a = Unit -> a
function Lazy(run) {
@i-am-tom
i-am-tom / pairs.js
Created April 27, 2017 08:44
Pair to Writer, with a little help from monoids.
const daggy = require('daggy')
const { uncurryN } = require('wi-jit') // Shameless plug :-)
// We'll need these instances for an example later...
Function.prototype.map = function (that) {
return x => that(this(x))
}
Function.prototype.ap = function (that) {
return x => that(x)(this(x))
@i-am-tom
i-am-tom / traversable.js
Last active November 1, 2018 09:05
A bunch of examples from the Traversable episode.
const Task = require('data.task')
const Either = require('fantasy-eithers')
// data.task actually uses `ap` with reversed
// arguments, as the spec originally did, so
// this is an "old-fashioned" lift2.
const lift2 = (f, a, b) => a.map(f).ap(b)
const queens = [ 'Alyssa', 'Katya', 'Willam' ]
@i-am-tom
i-am-tom / RoseTree.js
Created May 12, 2017 18:41
A Fantasy Land-Compliant Rose Tree.
const fl = require('fantasy-land')
//- Textbook rose tree.
//+ type RoseTree a = { value :: a, children :: [RoseTree a] }
function RoseTree(value, children) {
if (this.constructor !== RoseTree)
return new RoseTree(value, children)
Object.assign(this, { value, children })
}
@i-am-tom
i-am-tom / chain.js
Created May 15, 2017 19:57
The example code from the `Chain` post!
const Option = require('fantasy-options')
const Either = require('fantasy-eithers')
const Task = require('data.task')
const { tagged } = require('daggy')
const { Some, None } = Option
const { Left, Right } = Either
const Pair = tagged('_1', '_2')
@i-am-tom
i-am-tom / chainRec.js
Created May 30, 2017 16:42
Code from the fantas-eel post on ChainRec.
const daggy = require('daggy')
const { Loop, Done } =
daggy.taggedSum({ Loop: ['b']
, Done: ['a'] })
Array.empty = () => []
const Pair = T => {
const Pair_ = daggy.tagged('_1', '_2')
@i-am-tom
i-am-tom / monad.js
Created June 5, 2017 20:19
The Monad example from the Fantasy Land series.
const Promise = require('fantasy-promises')
const daggy = require('daggy')
//- Regular `compose` - old news!
//+ compose :: (b -> c)
//+ -> (a -> b)
//+ -> a -> c
const compose = f => g => x =>
f(g(x))
@i-am-tom
i-am-tom / extend.js
Created June 12, 2017 19:38
All the example code from the Extend article of Fantas, Eel, and Specification.
const daggy = require('daggy')
const { uncurryN } = require('wi-jit')
Array.prototype.empty = () => []
Sum = daggy.tagged('value')
Sum.prototype.concat = function (that) {
return Sum(this.value + that.value)
}
@i-am-tom
i-am-tom / Comonad.js
Created June 19, 2017 20:36
Code for Game of Life from the Comonad article.
const { tagged } = require('daggy')
const Pair = tagged('_1', '_2')
//+ data Store p s = Store (p -> s) p
const Store = tagged('lookup', 'pointer')
Array.prototype.equals = function (that) {
return this.length === that.length
&& this.every((x, i) => x.equals ? x.equals(that[i])