Created
April 8, 2016 23:10
-
-
Save gatlin/5b022bc38aa9f5a2b63a75580a056e8c to your computer and use it in GitHub Desktop.
Companion code to my essay on lists (http://niltag.net/essays/lists.html)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/** | |
* Our little list implementation | |
*/ | |
///// The foundation | |
let nil = (f) => (x) => x; | |
let cons = (h) => (t) => (f) => (x) => f(h)(t(f)(x)); | |
let foldr = (list) => (f) => (x) => list(f)(x); | |
///// List utilities | |
let length = (xs) => foldr(xs)((a) => (b) => b + 1)(0); | |
let map = (f) => (xs) => foldr(xs)( (y) => (ys) => cons(f(y))(ys) )(nil); | |
let filter = (cond) => (xs) => foldr | |
(xs) | |
( (value) => (already_filtered) => (f) => (x) => | |
cond(value) | |
? f(value)(foldr(already_filtered)(f)(x)) | |
: foldr(already_filtered)(f)(x)) | |
(nil); | |
let concat = (xs) => (ys) => foldr(xs)(cons)(ys); | |
let flatten = (xs) => foldr(xs)(concat)(nil); | |
let flatMap = (list) => (f) => flatten( map (f) (list) ); | |
let unit = (x) => cons (x) (nil); // constructs a unit list (one item) | |
// Allow us to print lists to the console | |
let show = (list) => list ( (a) => (b) => "" + a.toString() + b ) (""); | |
///// Demonstrations | |
let sum = (list) => foldr (list) ( (a) => (b) => a + b ) (0); | |
let list_1 = cons(1) (cons(2) (cons(3) (nil))); | |
let six = sum(list_1); | |
let three = length(list_1); | |
let twelve = sum ( map ( (x) => x * 2 ) (list_1) ); | |
let one_and_three = filter ( (x) => x % 2 !== 0 ) (list_1); | |
let person_a_groceries = cons ('rice') (cons ('oranges') (nil)); | |
let person_b_groceries = cons ('monster') (cons ('nos') (cons ('hot cheetos') | |
(nil))); | |
let shopping_list = flatten( cons (person_a_groceries) | |
( cons (person_b_groceries) | |
( nil ))); | |
///// More involved flatMap example | |
let customers = cons ('john') (cons ('jacob') (cons ('jingleheimer') (cons ('schmidt') (nil)))); | |
let categories = cons ('A') (cons ('B') (cons ('C') (nil))); | |
let products = function (category) { | |
if (category === 'A') { | |
return cons ('a1') (cons ('a2') (cons ('a3') (nil))); | |
} else if (category === 'B') { | |
return cons ('b1') (cons ('b2') (nil)); | |
} else if (category === 'C') { | |
return cons ('c1') (cons ('c2') (cons ('c3') (cons ('c4') (cons ('c5') (nil))))); | |
} else { | |
return nil; | |
} | |
}; | |
let likes = function(customer,category) { | |
if (customer === 'john' && (category === 'A' || category === 'C') | |
|| (customer === 'jacob' && (category === 'B')) | |
|| (customer === 'jingleheimer' && (category === 'B' || category === 'C')) | |
|| (customer === 'schmidt' && (category === 'A'))) { | |
return true; | |
} | |
return false; | |
}; | |
let ads = | |
flatMap (customers) ((customer) => | |
flatMap (categories) ((category) => | |
(likes(customer,category)) | |
? flatMap (products(category)) ((product) => | |
unit("Ad to: " + customer + " for " + product)) | |
: nil)); | |
console.log(show(ads)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment