Skip to content

Instantly share code, notes, and snippets.

View dtipson's full-sized avatar

Drew dtipson

View GitHub Profile
/*
So, let's play with some Semigroups and (maybe?) Monoids for combining lists in interesting ways
*/
//This one is pretty straightforward
//Union (keep all values from both lists, but no repeats)
const Union = function(xs){
if (!(this instanceof Union)) {
return new Union(xs);
}
// Let's make it possible to create pure functions even when we're
// dealing with impure operations that would have side effects!
// First we'll need a "Type" that can contain a (sometimes impure) function
function IO(fn) {
if (!(this instanceof IO)) {//make it simpler for end users to create a type without "new"
return new IO(fn);
}
this.runIO = fn;//IO now provides an extra control layer that allows the composition of unexecuted effects
@dtipson
dtipson / cellular automata with quasi-comonads.js
Last active November 9, 2021 14:41
Using a comonad(ish) pattern to create cellular automata in a more functional way. Inspired by this episode of funfunfunction: https://www.youtube.com/watch?v=bc-fVdbjAwk
/*
Native Arrays are not great structures for cellular automata.
Non-empty, circular, doubly-linked lists would be ideal...
but all we really need to do is write a comonadic-like interface
such that it _pretends_ that the array is circular, and can thus
pass the exfn below a sort of "local" slice of an Array as if it were circular.
So you can mostly ignore the implementation mess below
*/
Array.prototype.extendNear = function(exfn){
const len = this.length;
@dtipson
dtipson / IO plus Array & Promise helpers.js
Last active October 1, 2019 07:56
Bare bones FP type utility lib so we can play around with functions that capture the composition of DOM read/writes, but in a pure way
// Let's make it possible to create pure functions even when we're
// dealing with impure operations that would have side effects!
// First we'll need a "Type" that can contain a (sometimes impure) function
function IO(fn) {
if (!(this instanceof IO)) {//make it simpler for end users to create a type without "new"
return new IO(fn);
}
this.runIO = fn;//IO now provides an extra control layer that allows the composition of unexecuted effects
@dtipson
dtipson / jqueryreact.3v2.16v2.js
Last active November 16, 2016 21:56
Chainable, pure DOM manipulation operations married to a powerful DOM selector engine, just 202 bytes gzipped!
const IO = fn =>({
runIO: fn,//run the effect
map: f => IO( a => f(fn(a)) ),//transform the inner value
chain: f => IO( _ => f(fn()).runIO() ),//transform the inner value into another pure operation
fork: _ => IO(x => new Promise(r => window.setTimeout(_ => r(fn(x)), 0) ))//fork the process!
});
IO.of = x => IO(_ => x);
IO.$ = selectors => IO(_=>Array.from(document.querySelectorAll(selectors)));
//Examples:
const Nothing = new (class Nothing {
constructor() {}
ap() { return this; }
map() { return this; }
chain() { return this; }
reduce(f, x){ return x; }
getOrElse(x){ return x; }
concat(x){ return x; }
cata({Nothing}){ return Nothing(); }//this is NOT the Nothing type constructor here, btw, but a string method!
cataTap({Nothing}){ if(Nothing){ Nothing(); } return this; }
@dtipson
dtipson / inlineFuncAsWorker.js
Last active June 5, 2017 09:41
Another simple implementation of pushing a potentially costly operation off to a worker thread
//main function for creating an inline worker:
//inlineWorker:: Function -> a -> Promise b
const inlineWorker = fn => msg => {
const scriptString = `const func = ${fn.toString()};
addEventListener('message', function(e) {
Promise.resolve(e.data)
.then(func)
.then(postMessage);
}, false);
`;
@dtipson
dtipson / workerFactory.js
Last active March 15, 2020 15:39
Template literals allow us to write string code suitable for workers. We can even import actual functions using toString. Blob urls allow us to turn all that content into a script for the worker to run, allowing us to create and run one with no external dependencies!
//actual function (must be a named function declaration for use w/ toString here)
function addOne(x){ return x+1 };
//the actual worker code can be written as a string
//template literals make that convienient because they support multiline
//note that the addOne function above can be used in this worker code, since we'll be importing it
const workerScript = `
self.addEventListener('message', function(e) {
var data = e.data;
console.log('worker recieved: ',data);
@dtipson
dtipson / symbol.based.extensions.js
Last active January 21, 2016 20:47
Using Symbols to extend native prototypes in a way that cannot possibly clash with native extensions added in the future
const e = {};//define a store of possible props we want to add
(function(e){
const empty = Symbol('empty');
const _empty = ()=>[];
const flatten = Symbol('flatten');
function _flatten(){
return this.reduce( (a,b) => a.concat(b), []);
}
@dtipson
dtipson / requestIdleStack.js
Last active December 15, 2015 18:03
requestIdleCallback usage pattern that simplifies things a tiny bit
//always include a polyfill that falls back to setTimeout(cb,1) https://gist.github.com/paullewis/55efe5d6f05434a96c36
//or possibly something better https://github.com/PixelsCommander/requestIdleCallback-polyfill
//calling this function creates and returns a new stack of idle functions,
//and exposes an addTasks method that will add more to the stack as needed and return a cancelIdleCallback cancelable id
function createIdleStack(){
var bgtasks = [];//array of all tasks
function backgroundTask(deadline){
//does each task in order, checking to see if there's time left