[Functional Programming] Running though a serial number prediction functions for tagging, pairing the result into object
Let's we have some prediction functions, for each prediction function has a corresponding tag:
const {gt, lte, gte, lt} = require('ramda');
const {flip} = require('crocks'); const getSmlPred = and(flip(gt, -), flip(lte, ));
const getMedPred = and(flip(gt, 50), flip(lte, ));
const getLrgPred = flip(gt, );
// taggedPred :: (b, (a -> Boolean))
// taggedPreds :: [taggedPred]
const taggedPreds = [
['Sml', getSmlPred],
['Med', getMedPred],
['Lrg', getLrgPred]
];
So if we have input as:
-> 'Sml';
-> 'Med'
-> 'Lrg'
Also we wish our program to the safe, we want:
- -> Nothing
We can write a quick test function:
const {gt, lte, gte, lt} = require('ramda'); const {First, mreduceMap, and, safe, option, flip, objOf, assoc, not,
merge, identity, fanout, curry, compose, map, constant} = require('crocks'); const getSmlPred = and(flip(gt, -1), flip(lte, 50));
const getMedPred = and(flip(gt, 50), flip(lte, 100));
const getLrgred = flip(gt, 50);
// taggedPred :: (b, (a -> Boolean))
// taggedPreds :: [taggedPred]
const taggedPreds = [
['Sml', getSmlPred],
['Med', getMedPred],
['Lrg', getLrgred]
]; const fn = curry(([tag, pred]) => x => safe(pred)(x)
.map(constant(tag))); console.log('40 - Sml', fn(taggedPreds[0], 40)); // Just "Sml"
console.log('60 - Med', fn(taggedPreds[1], 60)); // Just "Med"
console.log('101 - Lrg', fn(taggedPreds[2], 101)); // Just "Lrg"
We can refactor the code into a more pointfree style and rename the testing 'fn' to 'tagValue':
const {gt, lte, gte, lt} = require('ramda'); const {First, mreduceMap, and, safe, option, flip, objOf, assoc, not,
merge, identity, fanout, curry, compose, map, constant} = require('crocks'); const getSmlPred = and(flip(gt, -), flip(lte, ));
const getMedPred = and(flip(gt, 50), flip(lte, ));
const getLrgred = flip(gt, );
// taggedPred :: (b, (a -> Boolean))
// taggedPreds :: [taggedPred]
const taggedPreds = [
['Sml', getSmlPred],
['Med', getMedPred],
['Lrg', getLrgred]
];
// tagValue :: taggedPred -> a -> Maybe b
const tagValue = curry(([tag, pred]) => compose(
map(constant(tag)),
safe(pred)
)); console.log('40 - Sml', tagValue(taggedPreds[], )); // Just "Sml"
console.log('60 - Med', tagValue(taggedPreds[], )); // Just "Med"
console.log('101 - Lrg', tagValue(taggedPreds[], )); // Just "Lrg"
console.log('-1 - Nothing', tagValue(taggedPreds[], -)); // Nothing "Nothing"
Now, what we want is create fews functions, we know that we want data comes last, we want to partiaclly apply the predcitions functions.
// match :: [ taggedPreds ] -> a -> Maybe b
const match =
flip(x => mreduceMap(First, flip(tagValue, x)));
const matchNumber = match(taggedPreds);
console.log('matchNumber', matchNumber()); // Just "Sml"
'mreduceMap': it take Monoid for combine the data together, here we use 'First', so only take the first Maybe result.
Then for each [tag, pred], we will run with tagValue([tag, pred], x), because [tag, pred] will be partiaclly applied last, but 'tagValue' function takes it as first arguement, so we have to use 'flip'. And apply 'x' first.
In the test code above, we get ''Just Sml" back for number 49. It is good, but not enough, what we really want is keeping a Pair(a, s), for example: Pair('Sml', 40); we can keep the original state together with the tag result.
What we can do is using 'fanout', which take two functions and generate a Pair:
const tagCard = fanout(compose(option(' | '), matchNumber), objOf('number'));
console.log('tagCard', tagCard()); // Pair( "Sml", { number: 49 } )
Lastly, we want to have the final result as:
const cardFromNumber = compose(
merge(assoc('type')),
tagCard
); console.log(
cardFromNumber()
) // { number: 101, type: 'Lrg' }
Full Code:
---
const {gt, lte} = require('ramda'); const {First, mreduceMap, and, safe, option, flip, objOf, assoc,
merge, fanout, curry, compose, map, constant} = require('crocks'); const getSmlPred = and(flip(gt, -), flip(lte, ));
const getMedPred = and(flip(gt, ), flip(lte, ));
const getLrgred = flip(gt, );
// taggedPred :: (b, (a -> Boolean))
// taggedPreds :: [taggedPred]
const taggedPreds = [
['Sml', getSmlPred],
['Med', getMedPred],
['Lrg', getLrgred]
]; // tagValue :: taggedPred -> a -> Maybe b
const tagValue = curry(([tag, pred]) => compose(
map(constant(tag)),
safe(pred)
)); // match :: [ taggedPreds ] -> a -> Maybe b
const match =
flip(x => mreduceMap(First, flip(tagValue, x)));
const matchNumber = match(taggedPreds); const tagCard = fanout(compose(option(' | '), matchNumber), objOf('number')); const cardFromNumber = compose(
merge(assoc('type')),
tagCard
) console.log(
cardFromNumber()
) // { number: 101, type: 'Lrg' }
---
This coding partten is useful, because we can keep the structure, just replace the tags and predications functions:
// data.js
const {test} = require('ramda'); module.exports = [
['Diners - Carte Blanche|diners', test(/^[-]/)],
['Diners|diners', test(/^([-]||)/)],
['JCB|jcb', test(/^([]|[-][-])/)],
['AMEX|american-express', test(/^[]/)],
['Visa Electron|visa', test(/^(||||(|))/)]
]
const {gt, lte} = require('ramda'); const {First, mreduceMap, and, safe, option, flip, objOf, assoc,
merge, fanout, curry, compose, map, constant} = require('crocks'); const getSmlPred = and(flip(gt, -), flip(lte, ));
const getMedPred = and(flip(gt, ), flip(lte, ));
const getLrgred = flip(gt, );
// taggedPred :: (b, (a -> Boolean))
// taggedPreds :: [taggedPred]
const taggedPreds = require('./data.js');
// tagValue :: taggedPred -> a -> Maybe b
const tagValue = curry(([tag, pred]) => compose(
map(constant(tag)),
safe(pred)
)); // match :: [ taggedPreds ] -> a -> Maybe b
const match =
flip(x => mreduceMap(First, flip(tagValue, x)));
const matchNumber = match(taggedPreds); const tagCard = fanout(compose(option(' | '), matchNumber), objOf('number')); const cardFromNumber = compose(
merge(assoc('type')),
tagCard
) console.log(
cardFromNumber('4026-xxxx-xxxxx-xxxx')
) // { number: '4026-xxxx-xxxxx-xxxx', type: 'Visa Electron|visa' }
[Functional Programming] Running though a serial number prediction functions for tagging, pairing the result into object的更多相关文章
- 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 ...
- Beginning Scala study note(4) Functional Programming in Scala
1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...
- BETTER SUPPORT FOR FUNCTIONAL PROGRAMMING IN ANGULAR 2
In this blog post I will talk about the changes coming in Angular 2 that will improve its support fo ...
- Functional Programming without Lambda - Part 2 Lifting, Functor, Monad
Lifting Now, let's review map from another perspective. map :: (T -> R) -> [T] -> [R] accep ...
- 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 ...
- Functional programming
In computer science, functional programming is a programming paradigm, a style of building the struc ...
- Source insight 3572版本安装及An invalid source insight serial number was detected解决方法
Source insight有最新版3572.3.50.0076 下载连接:http://www.sourceinsight.com/down35.html, http://www.sourcei ...
- Volume serial number could associate file existence on certain volume
When it comes to lnk file analysis, we should put more emphasis on the volume serial number. It coul ...
- Source insight 3572安装和版本号An invalid source insight serial number was detected解
Source insight最新版本3572 下载链接:http://www.sourceinsight.com/down35.html, http://www.sourceinsight.com ...
随机推荐
- Android 程序目录介绍
还是回到 Eclipse 中,首先展开 HelloWorld 项目,你会看到如图 1.17 所示的目录结构. 图 1.17 一开始看到这么多陌生的东西,你一定会感到有点头晕吧.别担心,我现在就对上 ...
- java链表知识点总结
下面是一个Link类定义的一部分.它包含了一些数据和下一个链结点的引用: ? 1 2 3 4 5 class Link { public int data; public int id ...
- How To Create A Local Repository For SUSE Linux
原文地址:http://candon123.blog.51cto.com/704299/1009294/ As you know,you can use the yum command to inst ...
- Highcharts.Chart
Highcharts 是一个使用javascript 脚本来生成图表的工具,和jfreechart 作用类似,都用来生成各种图表,并支持图片的导出和打印. 从官网 www.highcharts.com ...
- 【POI】maven引用POI的依赖,XSSFWorkbook依旧无法使用的问题。
maven项目引用POI的jar: <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependenc ...
- oracle exp/imp命令详解
E:\>exp help=y 通过输入 EXP 命令和用户名/口令,您可以 在用户 / 口令之后的命令: 实例: EXP SCOTT/TIGER 或者,您也可以通过输入跟有各种参数的 EXP 命 ...
- script标签加载顺序(defer & async)
script 拥有的属性 async:可选,表示应该立即下载脚本,但不应妨碍页面中的其他操作,比如下载其他资源或等待加载其他脚本.只对外部脚本文件有效. charset:可选.表示通过 src 属性指 ...
- 为python安装matplotlib模块
matplotlib是python中强大的画图模块. 首先确保已经安装python,然后用pip来安装matplotlib模块. 进入到cmd窗口下,执行python -m pip install - ...
- 黑吃黑第四季/全集Banshee迅雷下载
英文全名Banshee,第5季(2015)Cinemax. 本季看点:<黑吃黑>Ana Ayora加盟第四季,将会饰演Nina Cruz,表面上是在镇里一个聪明而又强悍的新副警长,但实际是 ...
- sublime text的扩展插件
sublime text用作开发编辑器,还缺省二个比较重要功能:跨文件跳转.返回最后一次编辑的位置: 这里有二个插件正好解决此问题:CTags.ChangeList 其它常用的插件,google一 ...