[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 ...
随机推荐
- How to convert a byte to its binary string representation
How to convert a byte to its binary string representation For example, the bits in a byte B are 1000 ...
- c# SerialPort会出现“已关闭 Safe handle”的错误
c# SerialPort使用时出现“已关闭 Safe handle”的错误我在开发SerialPort程序时出现了一个问题,在一段特殊的扫描代码的时候会出现“已关闭 Safe handle”的错误, ...
- 【Android基础篇】TabWidget设置背景和字体
在使用TabHost实现底部导航栏时,底部导航栏的三个导航button无法在布局文件中进行定制.比方设置点击时的颜色.字体的大小及颜色等,这里提供了一个解决的方法.就是在代码里进行定制. 思路是在Ac ...
- AngularJS自定义Directive不一定返回对象
AngularJS中,当需要自定义Directive时,通常返回一个对象,就像如下的写法: angular.module('modulename') .directive('myDirective', ...
- C#编程(二十七)----------创建泛型类
创建泛型类 首先介绍一个一般的,非泛型的简化链表类,可以包含任意类型的对象,以后再把这个类转化为泛型类. 在立案表中,一个元素引用下一个元素.所以必须创建一个类,他将对象封装在链表中,并引用下一个对象 ...
- pthread_join与pthread_detach细节问题
http://www.360doc.com/content/13/0106/09/9171956_258497083.shtml pthread_t pthr; pthread_create(& ...
- Android 百度地图开发(三)
实现比例尺功能和替换自带的缩放组件 ScaleView是比例尺控件.ZoomControlView是缩放控件,MainActivity就是我们的主界面了 先看下ZoomControlView类.代码例 ...
- source insight设置tab键为4个空格
首先通过路径(Options->Document Options)进入以下界面: step 1:将 Visible tabs 打勾. step 2 :将 Expand Tabs 打勾. step ...
- SharePoint 应用程序页匿名
前言 最近,有朋友问开发应用程序页,都是需要先登录再访问,无法开发匿名的应用程序页. 解决方法 其实,SharePoint帮我们提供了匿名访问的应用程序页的方法,只是和普通应用程序页继承的基类不一样, ...
- 识骨寻踪第一季/全集Bones迅雷下载
第一季 Bones Season 1 (2005)看点:这是一部专门从“骨头”上寻找破案线索的刑侦剧.女博士布莱南绰号“骨头”(艾米丽·丹斯切尔 Emily Deschanel 饰),是个学识渊博.专 ...