[Functional Programming] mapReduce over Async operations and fanout results in Pair(rejected, resolved) (fanout, flip, mapReduce)
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)的更多相关文章
- [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 ...
- [Functional Programming] Use Task/Async for Asynchronous Actions
We refactor a standard node callback style workflow into a composed task-based workflow. Original Co ...
- [Functional Programming] Reader with Async ADT
ReaderT is a Monad Transformer that wraps a given Monad with a Reader. This allows the interface of ...
- Functional Programming without Lambda - Part 2 Lifting, Functor, Monad
Lifting Now, let's review map from another perspective. map :: (T -> R) -> [T] -> [R] accep ...
- Monad (functional programming)
In functional programming, a monad is a design pattern that defines how functions, actions, inputs, ...
- JavaScript Functional Programming
JavaScript Functional Programming JavaScript 函数式编程 anonymous function https://en.wikipedia.org/wiki/ ...
- Beginning Scala study note(4) Functional Programming in Scala
1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...
- 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 ...
- 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 ...
随机推荐
- windows下安装awstats来分析apache的访问日志
一.啰嗦两句 之前在Windows下用Apache时,也曾经配置过Awstats,然后换了工作,改用Linux+nginx,渐渐把Apache忘记了.又换了工作,又得用Apache,这回版本更新到2. ...
- 【51nod-1239&1244】欧拉函数之和&莫比乌斯函数之和 杜教筛
题目链接: 1239:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1239 1244:http://www.51nod. ...
- HDU 1698 just a hook 线段树,区间定值,求和
Just a Hook Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1 ...
- The YubiKey -- HOW IT WORKS
A single YubiKey has multiple functions for protecting access to your email, your apps and your phys ...
- 运用Android ROM Manager应用安装ClockworkMod Recovery的详细教程
在安装ClockworkMod Recovery恢复模式之前,建议先认识下Google Android平台的ClockworkMod Recovery恢复模式 对于Android ROM Manage ...
- redhat 6.6 安装 (LVM)
http://www.cnblogs.com/kerrycode/p/4341960.html
- 普天通信JavaEE开发岗面试题
1 EJB中有几种Bean,叙述有状态Bean和无状态Bean的差别. 答:EJB中有Session Bean,Entity Bean,以及 Message Driven Bean.这两种的 Sess ...
- 关于TFS2010 远程无法创建团队项目的若干问题总结
今天遇到一个TFS的问题,折腾了好几个小时,故将其记录,给有遇到类似问题的朋友一些参考. 1.本文前提:服务器端只安装了TFS2010,本地没有安装Visual Studio 2010,因此不能在服务 ...
- 线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁
当涉及到多线程共享数据,需要数据同步的时候,就可以考虑使用线程锁了.本篇体验线程锁的各种用法以及线程死锁.主要包括: ※ 使用lock处理数据同步※ 使用Monitor.Enter和Monitor.E ...
- Oracle的数据类型
Oracle基本数据类型(亦叫内置数据类型 built-in datatypes)可以按类型分为: 字符串类型.数字类型.日期类型.LOB类型.LONG RAW& RAW类型.ROWID &a ...