This post is similar to previous post. The difference is in this post, we are going to see how to handle both successfuly result and error result by using Pair functor.

So, still we have our funs.js: which is the same as previous post.

const fs = require('fs');
const {Async, constant, composeK, curry} = require('crocks');
const {fromNode} = Async; const access = fromNode(fs.access);
const readFile = fromNode(fs.readFile); const accessAsync = curry((mode, path) =>
access(path, mode)
.map(constant(path))); // readFileAsync :: Option -> a -> Async Error b
const readFileAsync = curry((option, path) =>
readFile(path, option)); const checkRead = accessAsync(fs.constants.F_OK);
const readTextFile = readFileAsync('utf-8'); // loadTextFile :: String -> Async Error String
const loadTextFile = composeK(
readTextFile,
checkRead
); const fork = a => a.fork(
console.log.bind(null, 'rej'),
console.log.bind(null, 'res')
); module.exports = {
loadTextFile,
fork
}

For our main.js, we still have the same data input:

const data = [
'text.txt',
'text.big.txt',
'notfound.txt',
];

This time the difference of requirements are:

1. we want to read those files one by one, keep all the successfully results in Pair(result, _);

2. we want to keep the error result in Pair(_, error);

const concatSpecial = (acc, currAsync) =>
acc.chain(
xs => currAsync.bimap(
e => Pair(xs, e),
currVal => xs.concat(currVal))
); // Async (Pair [String] Error) [String]
const flow = mapReduce(
loadTextFile,
concatSpecial,
Async.Resolved([])
); flow(data).fork(
e => console.log(e.snd(), e.fst()), // Pair(success, error)
r => console.log(r), // Just success result
)

We are still using 'mapRedcue' to map over each filename, fetching the content; then we call 'concatSpecial' method, we want to concat all the successful result into one array. Therefore we give an empty array wrapped in Async:

const flow = mapReduce(
loadTextFile,
concatSpecial,
Async.Resolved([])
);

We can do some pointfree refactor for 'concatSpical', it's not necssary, but just as a partice:

const fn = flip(
xs => bimap(
e => Pair(xs, e),
currVal => xs.concat(currVal)
)
); const concatSpecial = (acc, currAsync) =>
acc.chain(
fn(currAsync)
);

For the function 'fn', we should take 'xs' as first param, then 'currAsync' as second param.

But since we also pass in 'currAsync' as first param, then we need to use 'flip':

acc.chain(
fn(currAsync) // pass currAsync as firt, then xs => fn(currAsync)(xs)
);

We can also replace 'Pair' with 'fanout':

const fn = flip(
xs => bimap(
fanout(constant(xs), identity),
currVal => xs.concat(currVal)
)
);

---

Full code:

const {fork, loadTextFile} = require('./funs.js');
const {Async, bimap, fanout, constant, flip, Pair, identity, mapReduce} = require('crocks'); const data = [
'text.txt',
'text.big.txt',
'notfound.txt',
]; const fn = flip(
xs => bimap(
e => Pair(xs, e),
fanout(constant(xs), identity),
currVal => xs.concat(currVal)
)
);
/*
const concatSpecial = (acc, currAsync) =>
acc.chain(
xs => currAsync.bimap(
e => Pair(xs, e),
currVal => xs.concat(currVal))
);*/
const concatSpecial = (acc, currAsync) =>
acc.chain(
fn(currAsync)
);
// Async (Pair [String] Error) [String]
const flow = mapReduce(
loadTextFile,
concatSpecial,
Async.Resolved([])
); flow(data).fork(
e => console.log(e.snd(), e.fst()), // Pair(success, error)
r => console.log(r), // Just success result
)

[Functional Programming] mapReduce over Async operations and fanout results in Pair(rejected, resolved) (fanout, flip, mapReduce)的更多相关文章

  1. [Functional Programming] mapReduce over Async operations with first success prediction (fromNode, alt, mapReduce, maybeToAsync)

    Let's say we are going to read some files, return the first file which pass the prediction method, t ...

  2. [Functional Programming] Use Task/Async for Asynchronous Actions

    We refactor a standard node callback style workflow into a composed task-based workflow. Original Co ...

  3. [Functional Programming] Reader with Async ADT

    ReaderT is a Monad Transformer that wraps a given Monad with a Reader. This allows the interface of ...

  4. Functional Programming without Lambda - Part 2 Lifting, Functor, Monad

    Lifting Now, let's review map from another perspective. map :: (T -> R) -> [T] -> [R] accep ...

  5. Monad (functional programming)

    In functional programming, a monad is a design pattern that defines how functions, actions, inputs, ...

  6. JavaScript Functional Programming

    JavaScript Functional Programming JavaScript 函数式编程 anonymous function https://en.wikipedia.org/wiki/ ...

  7. Beginning Scala study note(4) Functional Programming in Scala

    1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...

  8. Functional Programming without Lambda - Part 1 Functional Composition

    Functions in Java Prior to the introduction of Lambda Expressions feature in version 8, Java had lon ...

  9. a primary example for Functional programming in javascript

    background In pursuit of a real-world application, let’s say we need an e-commerce web applicationfo ...

随机推荐

  1. 2-SAT的一些题目

    http://blog.sina.com.cn/s/blog_64675f540100k2xj.html 都一个类型的不是很想写.

  2. Codeforces Beta Round #97 (Div. 1) B. Rectangle and Square 暴力

    B. Rectangle and Square 题目连接: http://codeforces.com/contest/135/problem/B Description Little Petya v ...

  3. poj 3630 Phone List 贪心

    Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 23722   Accepted: 7289 Descr ...

  4. Illegal instruction错误的定位---忽略编译期警告的代价

    在原计算机的linux c++程序可以正确跑起来,但是换了一台机器运行时出现致命错误,程序直接当掉,错误提示如下: Illegal instruction (core dumped) 造成改错的主要原 ...

  5. cocos2dx 字符串拼接

    ;i<;i++){ ]; sprintf(str,"%d",i); ]; strcpy(totalFilename, "game_loading") ; ...

  6. Linux服务器压测/拷机软件收集

    最近公司采购了一批服务器,于是收集了一些拷机软件来压测服务器硬件性能.硬件的稳定相对来说比较重要,7x24小时无间断运行,主要看三个硬件:CPU.内存.硬盘. 下面是收集的一些教程,可能网址已经失效了 ...

  7. IntelliJ IDEA代码分屏显示

  8. HDOJ 4876 ZCC loves cards

    枚举组合,在不考虑连续的情况下推断能否够覆盖L...R,对随机数据是一个非常大的减枝. 通过检測的暴力计算一遍 ZCC loves cards Time Limit: 4000/2000 MS (Ja ...

  9. 委托、多播委托、泛型委托Func,Action,Predicate,ExpressionTree

    当试图通过一个事件触发多个方法,抽象出泛型行为的时候,或许可以考虑使用委托.     通过委托构造函数或委托变量把方法赋值给委托 private delegate double DiscountDel ...

  10. 使用Redis实现抢购的一种思路(list队列实现)

    原文:https://my.oschina.net/chinaxy/blog/1829233 抢购是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如 ...