From f07abc502391693db3153ac5c4b646ca1a6e27d9 Mon Sep 17 00:00:00 2001 From: Ian Hofmann-Hicks Date: Sat, 25 Mar 2017 09:23:20 -0700 Subject: [PATCH] have tryCatch return a Result instead of an Either (#114) --- README.md | 8 ++++---- helpers/tryCatch.js | 10 +++++----- helpers/tryCatch.spec.js | 24 ++++++++++++++++++------ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 4c2ea46a0..fc33ee73c 100644 --- a/README.md +++ b/README.md @@ -295,9 +295,9 @@ It is hard knowing what is going on inside of some of these ADTs or your wonderf #### tryCatch ```haskell -tryCatch : (a -> b) -> a -> Either e b +tryCatch : (a -> b) -> a -> Result e b ``` -Typical try-catch blocks are very imperative in their usage. This `tryCatch` function provides a means of capturing that imperative nature in a simple declarative style. Pass it a function that could fail and it will return you another function wrapping the first function. When called the new function will either return the result in an `Either.Right` if everything was good, or an error wrapped in an `Either.Left` if it fails. +Typical try-catch blocks are very imperative in their usage. This `tryCatch` function provides a means of capturing that imperative nature in a simple declarative style. Pass it a function that could fail and it will return you another function wrapping the first function. When called, the new function will either return the result in a `Result.Ok` if everything was good, or an error wrapped in an `Result.Err` if it fails. ### Logic Functions The functions in this section are used to represent logical branching in a declarative manner. Each of these functions require either `Pred`s or predicate functions in their input. Since these functions work with `Pred`s and predicate functions, rather than values, this allows for composeable, "lazy" evaluation. @@ -328,13 +328,13 @@ Say you have two predicate functions or `Pred`s and would like to combine them i #### unless ```haskell -unless : ((a -> Boolean) | Pred) -> (* -> a) -> * -> a +unless : ((a -> Boolean) | Pred) -> (a -> a) -> a -> a ``` There may come a time when you need to adjust a value when a condition is false, that is where `unless` can come into play. Just provide a predicate function (a function that returns a Boolean) and a function to apply your desired modification. This will get you back a function that when you pass it a value, it will evaluate it and if false, will run your value through the provided function. Either the original or modified value will be returned depending on the result of the predicate. Check out [`when`](#when) for a negated version of this function. #### when ```haskell -when : ((a -> Boolean) | Pred) -> (* -> a) -> * -> a +when : ((a -> Boolean) | Pred) -> (a -> a) -> a -> a ``` There may come a time when you need to adjust a value when a condition is true, that is where `when` can come into play. Just provide a predicate function (a function that returns a Boolean) and a function to apply your desired modification. This will get you back a function that when you pass it a value, it will evaluate it and if true, will run your value through the provided function. Either the original or modified value will be returned depending on the result of the predicate. Check out [`unless`](#unless) for a negated version of this function. diff --git a/helpers/tryCatch.js b/helpers/tryCatch.js index d6b104c8d..7d8a714ab 100644 --- a/helpers/tryCatch.js +++ b/helpers/tryCatch.js @@ -5,18 +5,18 @@ const isFunction = require('../predicates/isFunction') const curry = require('./curry') -const Either = require('../crocks/Either') +const Result = require('../crocks/Result') -const Left = Either.Left -const Right = Either.Right +const Err = Result.Err +const Ok = Result.Ok function tryCatch(fn) { if(!isFunction(fn)) { throw new TypeError('tryCatch: Function required for first argument') } return function(x) { - try { return Right(fn(x)) } - catch(e) { return Left(e) } + try { return Ok(fn(x)) } + catch(e) { return Err(e) } } } diff --git a/helpers/tryCatch.spec.js b/helpers/tryCatch.spec.js index ac8f3cbe8..eba537394 100644 --- a/helpers/tryCatch.spec.js +++ b/helpers/tryCatch.spec.js @@ -5,10 +5,14 @@ const bindFunc = helpers.bindFunc const noop = helpers.noop const isFunction = require('../predicates/isFunction') +const isSameType = require('../predicates/isSameType') const either = require('../pointfree/either') const constant = require('../combinators/constant') +const identity = require('../combinators/identity') + +const Result = require('../crocks/Result') const tryCatch = require('./tryCatch') @@ -34,17 +38,25 @@ test('tryCatch', t => { }) test('tryCatch functionality', t => { + const msg = 'silly error' + const f = x => x - const g = () => { throw new Error('silly error') } + const g = () => { throw new Error(msg) } const extract = - either(constant('left'), constant('right')) + either(identity, constant('Ok')) + + const ok = tryCatch(f, null) + const err = tryCatch(g, null) + + t.ok(isSameType(Result, ok), 'Non-error returns a Result') + t.ok(isSameType(Result, err), 'Error returns a Result') - const right = extract(tryCatch(f, null)) - const left = extract(tryCatch(g, null)) + const good = extract(ok) + const bad = extract(err) - t.equals(right, 'right', 'returns a Right when no error') - t.equals(left, 'left', 'returns a Left when error') + t.equals(good, 'Ok', 'returns an Ok when no error') + t.equals(bad.message, msg, 'returns an Err with error on error') t.end() })