Let's say we want to write a most simple implementation 'avg' function:

const avg = list => {
let sum = 0;
for(let i = 0; i < list.length; i++) {
sum += list[i]
}
return sum / list.length
}

Basiclly, the 'avg' function doing two things:

  • Calculate sum
  • Divide sum / length

It works fine for tiny / small application, but for the large application, we need to think about reuseablitiy. We want to breakdown one function and think about any reuseable partten, which later can be reused.

In the following examples, We want to bring in two libarays which are commonly used in FP. One is Ramda, another one is Crocks.

Currying:

First, we want to write 'sum' and 'devide' functions by ourselves:

const { curry, reduce, compose } = require("crocks");
const R = require("ramda"); const sum = reduce(R.add, 0);
// divideByLen :: [Number] -> Number -> Number
const divideByLen = curry(
compose(
R.flip(R.divide),
R.length
)
);

'sum' is simple, using 'reduce' from Crocks, you can also write JS reduce, doesn't matter.

What we need to explain is 'divideByLen' function.

  • Why 'curry'?

Basic we want to call divideByLen in two ways:

divideByLen([1,2,3], sum([1,2,3]))
divideByLen([1,2,3])(sum([1,2,3]))

[Notice] You need to bring in 'curry' from Crocks, it is more flexable.

  • Why 'flip'?

Because R.divide(sum, length), we need to feed the divide function with sum as first argement, then length as second arguement. But when we write code, length will be feeded frist, sum will be partially applied, it will come second, therefore we need to call 'flip'.

Bring all together:

const avg = list =>
compose(
divideByLen(list),
sum
)(list);

We notice that, we have to pass 'list' to both Sum(list) and divideByLen(list). The code looks not so good. Whenever you are facing the situation, you need to pass the same arguement to two functions in parallel. You can consider to using 'Partial Application'.

Partial Application:

// Ramda

const avg = R.converge(R.divide, [R.sum, R.length]);

We are using 'Ramda's converge' function, bascilly you have pass in a data, the data will be passed to R.sum(data) & R.length(data), the return results of those two functions, will be passed to R.divide(resOfSum, resOfLength).

//Crocks:

const { curry, fanout, merge, compose } = require("crocks");

const avg = compose(
merge(R.divide),
fanout(R.sum, R.length)
);

We are using the Pair ADT, the data will be passed to R.sum(data) & R.length(data) thought 'fanout' function, it returns Pair(resOfSum, resOfLength).

Then we use 'merge', it works with Pair ADT, we merge two results by R.divide(resOfSum, resOfLength).

[Functional Programming] From simple implementation to Currying to Partial Application的更多相关文章

  1. Currying vs Partial Application

    柯里化相当于函数重构: 偏函数相当于函数适配. So, what is the difference between currying and partial application? As we s ...

  2. [Functional Programming] Write simple Semigroups type

    An introduction to concatting items via the formal Semi-group interface. Semi-groups are simply a ty ...

  3. [Functional Programming] Compose Simple State ADT Transitions into One Complex Transaction

    State is a lazy datatype and as such we can combine many simple transitions into one very complex on ...

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

  5. Functional Programming without Lambda - Part 2 Lifting, Functor, Monad

    Lifting Now, let's review map from another perspective. map :: (T -> R) -> [T] -> [R] accep ...

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

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

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

  8. Functional programming

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

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

随机推荐

  1. hdu1506单调栈的宽度

    很好的题目,单调栈上的宽度如何求 题解:https://blog.csdn.net/baidu_35643793/article/details/64440095 单调队列和单调栈都是去除没有用的数据 ...

  2. 微信公众号开发JS-SDK(1.2)

    概述 微信js-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微 ...

  3. sql如何截取字符

    ---MSSQL1 .SUBSTRING返回字符.binary.text 或 image 表达式的一部分.有关可与该函数一起使用的有效 Microsoft? SQL Server? 数据类型的更多信息 ...

  4. 《转》Java与Http协议

    引言 http(超文本传输协议)是一个基于请求与响应模式的.无状态的.应用层的协议,常基于TCP的连接方式.HTTP协议的主要特点是:     1.支持客户/服务器模式.     2.简单快速:客户向 ...

  5. JQuery中的Ajax(六)

    一:Ajax请求jQuery.ajax(options) load(url,[data],[callback])jQuery.get(url,[data],[callback]) jQuery.get ...

  6. android Unable to inflate view tag without class attribute

    定位 到 问题 是 布局文件出错,   Unable to inflate view tag without class attribute 错误 原因 <view android:layout ...

  7. android adb命令 抓取系统各种 log

    getLog.bat: adb root adb remount adb wait-for-device adb logcat -v time > C:\log.txt 在Android中不同的 ...

  8. VEMap.DeleteAllShapeLayers 方法

    来源:https://msdn.microsoft.com/zh-cn/library/bb412514.aspx <!DOCTYPE html PUBLIC "-//W3C//DTD ...

  9. HDU1285 确定名次 拓扑排序

    Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委 ...

  10. win10 更新之后,无法开启wifi,“组或资源的状态不是执行请求操作的正确状态”

    netsh wlan netsh wlan start hostednetwork 请参考最新博客:http://www.cnblogs.com/tanrong/p/8184325.html 已尝试解 ...