Skip to content

Instantly share code, notes, and snippets.

@amite
Last active December 2, 2017 06:45
Show Gist options
  • Save amite/a2dae610b867104c592e677cc99042b3 to your computer and use it in GitHub Desktop.
Save amite/a2dae610b867104c592e677cc99042b3 to your computer and use it in GitHub Desktop.
Composing Predicates
const filterText = this.props.filterText;
const inStockOnly = this.props.inStockOnly;
// K-combinator, used to create "always true" predicates
const K = k => () => k;
// Curried Array.prototype.filter
const filter = pr => xs => xs.filter(pr);
// Predicate generators
const byStock = () => ({stock}) => stock !== false;
const byName = text => ({name}) => name.indexOf(text) !== -1;
// Wraps a predicate into a function that will take a boolean flag.
// If this flag is true, the predicate is returned. Otherwise, an always-true predicate is returned.
const conditionalPredicate = pr => flag => flag ? pr : K(true);
const byStockCond = conditionalPredicate(byStock());
const byNameCond = conditionalPredicate(byName(filterText));
// Joins predicates with logical conjunction (&&)
const joinPredicates = (...prs) => x => prs.every(pr => pr(x));
const buildFilter = (byStock, byName) => filter(joinPredicates(byStockCond(byStock), byNameCond(byName)));
const Just = v => ({
isJust: true,
value: v
});
const Nothing = { isJust: false };
const last = xs => xs.length > 0 ? Just(xs[xs.length-1]) : Nothing;
const catMaybes = xs => xs.reduce((newList, m) => m.isJust && newList.push(m.value), []);
const flatten = () => this.reduce((newList, l) => newList.concat(l), []);
const compose = f => g => x => f(g(x));
// ...
class ProductTable extends React.Component {
render() {
const filterText = this.props.filterText;
const inStockOnly = this.props.inStockOnly;
const rows = compose (catMaybes) (flatten)
(this.props.product
.filter(p => p.name.includes(filterText))
.filter(p => inStockOnly && !product.stocked)
.reduce((rows, p) => rows.push([last(rows), p]), [])
.map(([prev, curr]) => {
const lastCategory = prev.isJust ? prev.value.category : '';
return [
curr.category !== lastCategory ?
Just(<ProductCategoryRow
category={curr.category}
key={curr.category} />
) : Nothing,
Just(<ProductRow
product={product}
key={product.name}
/>)
];
}));
return (
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment