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. 数据储存为base64编码,如何实现模糊搜索

    假设字段title存储的是经过base64编码后的字符串,$key是存搜索关键字的变量 则普通的查询方法, select * from 表名 where title like '$key'; 无法正确 ...

  2. 冒泡排序之Java实现

    冒泡排序之Java实现 一.方法一 package cn.com.zfc.lesson21.sort; import java.util.Arrays; /** * * @title BubbleSo ...

  3. 洛谷 P4884 多少个1?

    题面在这里 好久没做题了2333,竟然还一次A了,神奇 大概就是等比数列然后把分母乘过去,然后直接BSGS就行了,就是要写快速乘恩... #include<bits/stdc++.h> # ...

  4. python开发_tkinter_修改tkinter窗口的红色图标'Tk'

    学过java的swing可能知道,在创建一个窗口的时候,窗口的左上角是一个咖啡图标 如下图所示: 在python中,tkinter模块生成的窗口左上角是一个:Tk字样的图标(Tk为tkinter的缩写 ...

  5. sunstudio 12.3 on solaris 10

    #include <stdio.h> #include <stdlib.h> #define RPT 10000000 int main() { int i=1; for( i ...

  6. Ubuntu下(Linux+Apache+MYSQL+PHP, LAMP)环境搭建

    近期開始玩PHP,于是试着搭建一下开发环境并做个记录,以备日后再使用起来方便可查. 第一步 确保软件包是最新的 sudo apt-get update 第二步 安装Apache2 sudo apt-g ...

  7. c#分页工具类,完美实现List分页

    using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Proje ...

  8. golang 关键字以及简单用法说明

    golang只有25个关键字 package: 定义包名, go中任何一个文件必须有一个package, 一般而言,package的定义和文件所属文件夹一致, 并且main函数所在文件的package ...

  9. RocketMQ的部署方式及持久化方式

    RocketMQ 的 Broker 有三种集群部署方式: 1. 单台 Master 部署: 2. 多台 Master部署: 3. 多 Master 多 Slave 部署:采用第 3 种部署方式时, M ...

  10. [Unity Editor]10行代码搞定Hierarchy排序

    在日常的工作和研究中,当给我们的场景摆放过多的物件的时候,Hierarchy面板就会变得杂乱不堪.比如这样:    过多的层次结构充斥在里面,根层的物件毫无序列可言,整个层次面板显示非常的杂乱不堪,如 ...