Last active
December 2, 2017 06:45
-
-
Save amite/a2dae610b867104c592e677cc99042b3 to your computer and use it in GitHub Desktop.
Composing Predicates
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
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))); |
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
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