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. bzoj2243树链剖分+区间合并

    树链上区间合并的问题比区间修改要复杂,因为每一条重链在线段树上分布一般都是不连续的,所以在进行链上操作时要手动将其合并起来,维护两个端点值 处理时的方向问题:lca->u是一个方向,lca-&g ...

  2. python 全栈开发,Day84(django请求生命周期,FBV和CBV,ORM拾遗,Git)

    一.django 请求生命周期 流程图: 1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post, ...

  3. Struts2(接受表单参数)请求数据自动封装和数据类型转换

    Struts2请求数据自动封装: (1)实现原理:参数拦截器 (2)方式1:jsp表单数据填充到action中的属性:        普通的成员变量,必须给set,get可以不给的.    注意点,A ...

  4. django引入现有数据库

    Django引入外部数据库还是比较方便的,步骤如下: 1.创建一个项目,修改seting文件,在setting里面设置你要连接的数据库类型和连接名称,地址之类,和创建新项目的时候一致. 2.运行下面代 ...

  5. Python open详解

    一.打开文件的模式有: 1.r,只读模式[默认]. 2.w,只写模式.[不可读,不存在则创建,存在则删除内容] 3.a,追加模式.[可读,不存在则创建,存在则只追加内容] 二.+ 表示可以同时读写某个 ...

  6. BZOJ1087 [SCOI2005]互不侵犯King 状态压缩动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1087 题意概括 在n*n的棋盘上面放k个国王,使得他们互相无法攻击,问有多少种摆法. 题解 dp[ ...

  7. python2与python3的差异

    最近在学习python3,遇到过几次python3与python2的的问题,python2使用,而到了python3就不适用了,就整理了一下自己到目前为止所遇到了几个问题(以下是小白见解) 1.pyt ...

  8. DP-hdu1260

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1260 题目描述: 题目大意:每一个人去电影票买票,有两种买票方法:1.自己单人买:2.与前面的人一起买 ...

  9. 中间人攻击工具mitmf(另类的XSS注入攻击)

    中间人攻击工具mitmf(另类的XSS注入攻击) (一)简介 (二)安装 (三)结合beef使用 (一)简介 Mitmf 是一款用来进行中间人攻击的工具.它可以结合 beef 一起来使用,并利用 be ...

  10. Get package name

    public class GetPackageName { public static void main(String[] args) { GetPackageName obj = new GetP ...