lazy-either

2.0.0 • Public • Published

LazyEither

Build Status

The LazyEither type is used to represent a lazy Either value. It is similar to the Future and Promise types. The constructor continuation function parameter and eventual return value is an Either type. The execution is delayed until the value is requested using one of it's methods.

The implementation is more favorable than the Future type because it is very easy to compose elegant pipelines, and it handles errors nicely. If fork-like branching is desired, it can be done just by resolving the pipeline using value and checking whether the result isLeft or isRight (though branching is not usually needed). See the examples section for more details.

The implementation follows the Fantasy Land specifications. The LazyEither type is a Functor, Applicative and Monad. It is not (necessarily) a Setoid due to its lazy/deferred nature.

Construction

The LazyEither type consists of a single constructor that accepts a function which must accept a continuation function used to resolve the LazyEither instance into an Either type:

LazyEither :: ((Either e a -> ()) -> ()) -> LazyEither e a

The resolved instance should be an Either type.

//:: (Number, a) -> LazyEither (Either e a)
let delayed = (ms, val) => LazyEither(resolve => {
  ms > 1000 ? resolve(S.Left(Error('Delay too long')))
            : setTimeout(() => resolve(S.Right(val)), ms)
})
delayed(500, 'Hello').value(console.log)  // returns Right('Hello')
delayed(1001, 'Hey').value(console.log)  // returns Left(Error('Delay too long'))

Interaction

Once a LazyEither instance has been created, the various methods attached to the instance can be used to instruct further transformations to take place. Nothing is actually executed until the value or fantasy-land/equals method is called.

The fantasy-land/map, fantasy-land/ap and fantasy-land/chain functions can be used to transform resolved values of a LazyEither instance.

//:: String -> String -> String
const join = S.curry2(path.join)
 
//:: String -> LazyEither (Either e [String])
const ls = path => LazyEither(resolve =>
  fs.readdir(path, (err, files) => resolve(err ? S.Left(err) : S.Right(S.map(join(path), files)))))
 
//:: String -> LazyEither (Either e String)
const cat = file => LazyEither(resolve =>
  fs.readFile(file, {encoding: 'utf8'}, (err, data) => resolve(err ? S.Left(err) : S.Right(data))))
 
//:: String -> LazyEither (Either e String)
const catDir =
S.pipe([ls,
        S.chain(S.traverse(LazyEither, cat)),
        S.map(S.unlines)])

A LazyEither instance is executed when value or fantasy-land/equals gets called:

catDir(os.homedir()).value(S.either(console.error, console.log))

Reference

Constructors

LazyEither

:: ((Either e a -> ()) -> ()) -> LazyEither e a

Constructs a LazyEither instance that represents some action that may possibly fail. It takes a function which must accept a continuation function that takes an Either type used to represent success or failure.

LazyEither.Right

:: a -> LazyEither e a

Creates a LazyEither instance that resolves to a Right with the given value.

LazyEither.Left

:: e -> LazyEither e a

Creates a LazyEither instance that resolves to a Left with the given value.

Static methods

LazyEither['fantasy-land/of']

:: a -> LazyEither e a

Creates a pure instance that resolves to a Right with the given value.

LazyEither.lift

:: (a -> b) -> a -> LazyEither e b

Lifts a function of arity 1 into one that returns a LazyEither instance.

LazyEither.liftN

:: n -> (a -> .. -> z) -> a -> .. -> z -> LazyEither e z

Lifts a function of arity n into one that returns a LazyEither instance.

LazyEither.promote

:: Either a b -> LazyEither a b

Promotes an Either type to a LazyEither type.

Instance methods

lazyEither['fantasy-land/map']

:: LazyEither e a ~> (a -> b) -> LazyEither e b

Transforms the resolved Either value of this LazyEither instance with the given function. If the instance resolves as a Left value, the provided function is not called and the returned LazyEither instance will resolve with that Left value.

lazyEither['fantasy-land/ap']

:: LazyEither e a ~> LazyEither e (a -> b) -> LazyEither e b

Applies the Either function of the provided LazyEither instance to the Either value of this LazyEither instance, producing a LazyEither instance of the result. If either LazyEither resolves as a Left value, then the returned LazyEither instance will resolve with that Left value.

lazyEither['fantasy-land/chain']

:: LazyEither e a ~> (a -> LazyEither e b) -> LazyEither e b

Calls the provided function with the value of this LazyEither instance, returning the new LazyEither instance. If either LazyEither instance resolves as a Left value, the returned LazyEither instance will resolve with that Left value. The provided function can be used to try to recover the error.

lazyEither['fantasy-land/bimap']

:: LazyEither e a ~> (e -> f) -> (a -> b) -> LazyEither f b

Uses the provided functions to transform this LazyEither instance when it resolves to a Left or a Right value, respectively.

lazyEither.value

:: LazyEither e a ~> (Either e a -> ()) -> ()

Calls the provided function with the value of this LazyEither instance without returning a new LazyEither instance. It is similar to Future.fork. This function can be used as a final processing step for the returned Either value, or to create a branch of two seperate execution streams to handle the resolved Left or Right value.

lazyEither['fantasy-land/equals']

:: LazyEither a b ~> LazyEither c d -> (Boolean -> ()) -> ()

Compares the Either value of this LazyEither instance with the Either value of the provided LazyEither instance, and calls the provided function with the Boolean result of the comparison. Like value, this function will resolve the pipeline. The result will return true if both Either values match or false if they do not match.

Dependencies (2)

Dev Dependencies (3)

Package Sidebar

Install

npm i lazy-either

Weekly Downloads

1

Version

2.0.0

License

MIT

Last publish

Collaborators

  • ristostevcev