[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 ...
随机推荐
- JTAG - General description of the TAP Controller states
A transition between the states only occurs on the rising edge of TCK, and each state has a differen ...
- linux 学习之路(学linux必看)
很多同学接触Linux不多,对Linux平台的开发更是一无所知. 而现在的趋势越来越表明,作为一个优秀的软件开发人员,或计算机IT行业从业人员, 掌握Linux是一种很重要的谋生资源与手段. 下来我将 ...
- VS Supercharger插件的破解
Supercharger我已经用了很多年了,感觉十分不错,最初使用的时候,是叫做CodeMap.不过要想很好的使用起来这个VS插件,需要对其进行细致的设置. 这里不再多说了,看下,这个软件怎么破解吧. ...
- UINavigationController 、UINavigationBar 、UINavigationItem 超清晰直观详解
UINavigationController 部分 1. UINavigationController 是一个容器类.里面盛放的是UIViewController. 容器的意思是,如果你不放入UIVi ...
- ifeq endif
ifeq ($(PLATFORM_VERSION),4.4)$(info "________________________4.4"); LOCAL_CFLAGS += -DPLU ...
- Ubuntu下 ssh : connect to host localhost port 22:Connection refused
Ubuntu下测试ssh时使用ssh localhost 命令,出现错误提示connect to host localhost port 22:Connection refused 造成这个错误的原因 ...
- cocos2d-x 真正的定时器之schedule
转载请注明,原文地址:http://blog.csdn.net/musicvs/article/details/8551066 正文: 1. 不调用update函数,调用自己的函数 其实原理是一样的, ...
- winform 给textbox 增加 或 减小字体大小 z
private void btnAddFont_Click(object sender, EventArgs e) { float fSize = this.txtResult.Font.Size; ...
- Unity3D 经常使用库
JSON.NET:http://james.newtonking.com/json LitJSON: http://lbv.github.io/litjson/ ProtoBuf - net:htt ...
- Spring4+quartz2集群借助邮箱或是短信实现生日的农历提醒(Quartz实现农历、阴历、公历生日提醒)
自己记性差,除了老婆.老大和自己的生日以外,一直记不住亲朋好友的生日,长辈们的生日基本上又都是用农历来算,公历的话,直接用Quartz设置循环提醒,农历就没辙了,每每搞的自己很尴尬,需要别人来提醒自己 ...