How to make Either Monads be aware of of Async functions(Promises/Future)

2k views Asked by At

I am trying to use Either Monad to pipe my data through, the problem is that I can't figure out how to make my Monad to be aware of the operation that is async

here is what I have

let processData = Either.either(_sendError, _sendResponse)

processData(_getDataGeneric(queryResult)
    .chain(_findDevice)
    .chain(_processRequest)
);

queryResult is what I fetch from the database itself.

the problem is that fetching the result is only in the middle of the pipeline. what I want is this

ValidateUserInput -> GetDataFromDB -> ProcessData

processAll(_fetchFromDB(userId)
    .getDataGeneric
    .chain(_findDevice)
    .chain(_processRequest))


//_fetchFromDB , Mongoose Query
 function _fetchFromDB(userId){
        return myModel.findOne({id:userId}).exec()
                                  .then(function(result){
                                     return Right(result)
                                }).catch((err)=>Left(err))
  }

if result is valid from DB,it will return an Right instance, and if there is any sort of error, it will return Left

the problem is that this operation is Async, and i am not sure how to get my Either Monad to handle it and process it.

Any ideas on how to make my Monad aware of Promises in its operation?

1

There are 1 answers

4
Scott Christopher On BEST ANSWER

As you're seeing, an Either type can only represent values that have already been realised, while the asynchronous operation represents something that may be evaluated in the future.

A Promise already combines the behaviour of an Either, by representing the possibility of both error and successful values. It also captures the behaviour of monadic-style chaining of operations by allowing then to return another Promise instance.

If however you're interested in something similar to a Promise that behaves more closely to an Either (and also follows the Fantasy Land spec) then you might like to look at one of the Future implementations such as Fluture

e.g.

import Future from 'fluture';

const processAll = Future.fork(_sendError, _sendResponse);

const _fetchFromDB =
  Future.fromPromise(userId => myModel.findOne({ id: userId }).exec())

processAll(_fetchFromDB(userId)
  .chain(getDataGeneric)
  .chain(_findDevice)
  .chain(_processRequest))