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的更多相关文章

  1. 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 ...

  2. Beginning Scala study note(4) Functional Programming in Scala

    1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...

  3. 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 ...

  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. 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 ...

  6. Functional programming

    In computer science, functional programming is a programming paradigm, a style of building the struc ...

  7. 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 ...

  8. 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 ...

  9. Source insight 3572安装和版本号An invalid source insight serial number was detected解

    Source insight最新版本3572 下载链接:http://www.sourceinsight.com/down35.html,   http://www.sourceinsight.com ...

随机推荐

  1. leetcode第一刷_N-Queens II

    这个题好无趣,竟然输出解的个数.前一个题把全部解都输出出来了.还愁不知道解的个数吗. . 我怀疑这个解的个数是有一个类似通项的东西,就上网查了一下.没有啊亲,最后就把上一题的代码略微改了一下过掉了. ...

  2. STM32F4 Timer External Clock TI2 Both Edges Demo

    #define CLK_FREQ ( 10000 ) #define CORE_FREQ ( 168000000 ) static void TIM_GPIO_Config( void ) { GPI ...

  3. 前端使用AngularJS的$resource,后端ASP.NET Web API,实现分页、过滤

    在上一篇中实现了增删改查,本篇实现分页和过滤. 本系列包括: 1.前端使用AngularJS的$resource,后端ASP.NET Web API,实现增删改查2.前端使用AngularJS的$re ...

  4. Android:Attribute is missing the Android namespace prefix

    今天编写XML文件时,出现了Attribute is missing the Android namespace prefix的错误,开始一直找没找出原因,后来仔细一看原来只是一个很简单的单词书写错误 ...

  5. TWebHttpRequest使用

    TWebHttpRequest使用 TWebHttpRequest通过HTTP GET方法,向中间件REST API申请数据. procedure TForm1.WebButton1Click(Sen ...

  6. 咏南中间件支持TMS WEB CORE客户端

    咏南中间件支持TMS WEB CORE客户端 TMS WEB CORE是优秀的JS前端,搭配咏南中间件后端,可以进行快速的企业应用开发.

  7. clientX, clientY,offsetX, offsetY,screenX, screenY, x, y

    clientX, clientY是鼠标当前相对于网页的位置,当鼠标位于页面左上角时clientX=0, clientY=0: offsetX, offsetY是鼠标当前相对于网页中的某一区域的位置,当 ...

  8. Java Swing 使用非本地字体

    package reyo; import java.awt.Container; import java.awt.Font; import java.awt.FontFormatException; ...

  9. 用代码获取APP启动页图片

    用代码获取APP启动页图片 源码 - swift // // AppleSystemService.swift // Swift-Animations // // Created by YouXian ...

  10. ListView单条刷新的方法

    我们一般会调用notifydatasetchange通知listView刷新界面.但会造成getView方法被多次调用(画面上能显示多少就会被调用多少次),如果是很明确的知道只更新了list中的某一个 ...