Skip to content

Instantly share code, notes, and snippets.

View mrtnbroder's full-sized avatar
🕶️
λ

Martin Broder mrtnbroder

🕶️
λ
View GitHub Profile
@mrtnbroder
mrtnbroder / fp_arch.js
Created April 4, 2019 06:19 — forked from DrBoolean/fp_arch.js
OO => FP architecture refactor
// Simple example, but the idea holds for more complex objects.
/* 1) Start with OO */
// user.js
class User {
constructor(firstName, lastName, email) {
this.firstName = firstName
this.lastName = lastName
// Utils
const range = n => [...Array(n).keys()];
const add = ([x0, y0]) => ([x1, y1]) => [x0 + x1, y0 + y1];
const rotate = θ => ([x, y]) => [
Math.round(x * Math.cos(θ) - y * Math.sin(θ)),
Math.round(x * Math.sin(θ) + y * Math.cos(θ))
];
const map = f => g =>
function*() {
for (const v of g()) {
@mrtnbroder
mrtnbroder / traversing_state.js
Created March 29, 2019 10:07 — forked from masaeedu/traversing_state.js
Refactoring to discover Arr.traverse and the State applicative
// This gist shows how to factor a concrete stateful fold in vanilla JS
// into a number of general purpose utilities that can be combined to recover
// the original behavior
// We're going to start from a particular code snippet and iteratively make
// small changes to it to get a finished product
// While reading this post, it is useful to have a diff tool at hand that allows
// you to compare snippets side by side and see what changed in each iteration
@mrtnbroder
mrtnbroder / interactive-config.js
Created November 1, 2018 09:06 — forked from i-am-tom/interactive-config.js
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
@mrtnbroder
mrtnbroder / Lazy.js
Created November 1, 2018 09:05 — forked from i-am-tom/Lazy.js
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) {
@mrtnbroder
mrtnbroder / pairs.js
Created November 1, 2018 09:05 — forked from i-am-tom/pairs.js
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))
@mrtnbroder
mrtnbroder / traversable.js
Created November 1, 2018 09:05 — forked from i-am-tom/traversable.js
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' ]
@mrtnbroder
mrtnbroder / RoseTree.js
Created November 1, 2018 09:04 — forked from i-am-tom/RoseTree.js
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 })
}
@mrtnbroder
mrtnbroder / ReaderTFuture.js
Created November 1, 2018 09:04 — forked from i-am-tom/ReaderTFuture.js
Config-dependent Future.
const Future = require('fluture')
// I can't guarantee this will work out of the box - it's quite old... but
// you should hopefully be able to see how this fits together!
const { ReaderT } = require('fantasy-readers')
// First of all, you're going to need to "lift" all your `Future` operations
// to work within ReaderT. Basically, you just need to call `ReaderT.lift` on
// any `Future` values.
const doAjaxThing_ = x => ReaderT.lift(doAjaxThing(x))
@mrtnbroder
mrtnbroder / semigroup.js
Created November 1, 2018 09:00 — forked from richdouglasevans/semigroup.js
Fantas, Eel, and Specification
import { tagged } from "daggy";
const First = tagged("First", ["val"]);
First.prototype.concat = function(that) {
return this;
};
const Min = tagged("Min", ["val"]);