Skip to content

Instantly share code, notes, and snippets.

View davidchambers's full-sized avatar

David Chambers davidchambers

View GitHub Profile
@davidchambers
davidchambers / ListLike.js
Created April 25, 2024 10:30
Goal: Write a function for testing any given “module” that provides a specific set of functions for creating and manipulating lists. This is trivial in JavaScript but tricky in Kotlin due to the lack of higher-kinded types.
import {deepStrictEqual as eq} from "node:assert";
// class ListLike f where
// empty :: f a
// cons :: a -> f a -> f a
// fold :: f a -> b -> (b -> a -> b) -> b
// map :: f a -> (a -> b) -> f b
// length :: f a -> Int
const Array = {

Function composition has one huge benefit over chaining APIs: it allows any combination of JavaScript functions to be stuck together to form a pipeline. One could create a pipeline involving a function from library A, a function from library B, a function from library C, and a built-in function. With a chaining API one is restricted to the set of functions available on the object facilitating the chaining.

I found this to be a problem when using Underscore. This would be fine for a pipeline comprised solely of Underscore functions (represented here by lower-case identifiers):

_(x)
.a(...)
.b(...)
.c(...)
.value()
import S from 'sanctuary';
import Identity from 'sanctuary-identity';
// lens :: (s -> a) -> (a -> s -> s) -> Lens s a
const lens = getter => setter => f => s => (
S.map (v => setter (v) (s))
(f (getter (s)))
);

Challenge

Write a function of type String -> Integer. The input may or may not be a valid JSON string. If it is valid, the resulting JavaScript value is expected to be an object, but may not be. If it is an object, it is expected to have a foo property whose value is expected to be an object, but may not be. This value is expected to have a bar property which is expected to be an object with a baz property whose value is expected to be an array of strings. Each of these strings is expected to be a hex representation of an integer (e.g. 0xFF). If every element of the array meets this expectation, the

//# zip :: Array a -> Array a -> Array a
//.
//. Zip two arrays, xs and ys, of arbitrary lengths.
//.
//. let n = Math.min (xs.length, ys.length);
//.
//. If the first array is longer than the second, the result will
//. consist of the first n + 1 elements of the first array and
//. all n elements of the second array. Otherwise, the result will
//. consist of the first n elements of each array.
//# groupBy :: (a -> b) -> Array a -> Array (Array a)
//.
//. Group the given elements in accordance with the given comparator.
//.
//. > groupBy (x => x % 3) ([1, 2, 3, 4, 5, 6, 7, 8, 9])
//. [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
const groupBy = f => xs => {
const groups = [];
const ys = [];
xs.forEach (x => {
'use strict';
const Future = require ('fluture');
const S = require ('sanctuary');
// data Action = Reset | Increment Integer | Decrement Integer
// Reset :: Action
const Reset = {tagName: 'Reset'};
@davidchambers
davidchambers / zip-many.js
Created October 17, 2014 18:07
zipMany implementation with Ramda, created with @benperez
var R = require('ramda');
var zipMany =
R.cond(R.isEmpty,
R.always([]),
R.converge(R.map,
R.flip(R.pluck),
R.pipe(R.head, R.length, R.range(0))));
var zipMany2 = function(lists) {
@davidchambers
davidchambers / comment.md
Created June 2, 2016 21:34
Quick introduction to chaining monads from a pull request review
var convertPercentage = function(percentage) {
  if (percentage == null) {
    return null;
  } else {
    return parseFloat(percentage.replace(/[^-\d.]/g, ''));
  }
};
@davidchambers
davidchambers / dataTransform.js
Created November 14, 2017 20:02 — forked from josete89/dataTransform.js
Data mapping with sanctuary
'use strict';
const R = require('ramda');
const S = require('sanctuary');
const data = {
id: 1,
orderName: 'Order from spain',
teamName: 'Portland penguins',