Based on that understanding I implemented an either function
// either := (left:(Error) => B, right:(A) => B)
// => (Continuable<A>) => Continuable<B>
function either(left, right) { return function duplex(source) {
return function continuable(callback) {
source(function (err, value) {
return err ? callback(null, left(err)) :
callback(null, right(value))
})
}
} }
Which then allowed me to remove an if (err) from my code!
// with either
router.addRoute("/posts", function (req, res) {
var posts = findPosts()
var subsetOfPosts = map(filterAndSort)(posts)
var payload = either(function (err) {
return {
statusCode: 500,
body: { message: err.message }
}
}, function (posts) {
return { statusCode: 200, body: posts }
})(subsetOfPosts)
payload(function (_, value) {
sendJson(req, res, value)
})
})
// without either
router.addRoute("/posts", function (req, res) {
var posts = findPosts()
var subsetOfPosts = map(filterAndSort)(posts)
subsetOfPosts(function (err, posts) {
if (err) {
return sendJson(req, res, {
statusCode: 500,
body: { message: err.message }
})
}
sendJson(req, res, {
statusCode: 200,
body: posts
})
})
})
In the above example using either(left, right) instead of a manual if doesn't actually make it any simpler but you can imagine it's an improvement for more complex cases
Continuable's are actually an asynchronous
Either
implementation(for reference. Explaining Scala Either, Explaining Either for errors in Haskell)
Based on that understanding I implemented an
either
functionWhich then allowed me to remove an
if (err)
from my code!In the above example using
either(left, right)
instead of a manualif
doesn't actually make it any simpler but you can imagine it's an improvement for more complex cases