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. 有关列分组,定义css样式无效的问题

    声明: web前端学习笔记,欢迎大神指点.联系QQ:1522025433. 有时候我们要单独对表格的某列定义单独的样式,就会很自然的想到 表格的 在<table>标签内使用的 <co ...

  2. 【C++ Primer | 10】STL算法

    第一部分 find(beg, end, val) equal(beg1, end, beg2) min(val1, val2) max(val1, val2) min_element(beg, end ...

  3. join 关键字

    参考:http://www.blogjava.net/vincent/archive/2008/08/23/223912.html

  4. python全栈开发day22-常用模块二(hashlib、configparse、logging)

    一.昨日内容回顾 1.钻石继承 #新式类,本身或父类显示继承object #找名字的时候是广度优先顺序 #有mro方法,super方法, # super并不是单纯的找父类,和mro顺序是完全对应的 # ...

  5. Jmeter如何提取响应头部的JSESSIONID

    近期有柠檬班的学生找到华华,问了一个问题,就是利用Jmeter做接口测试的时候,如何提取头部的JSESSIONID然后传递到下一个请求,继续完成当前用户的请求. 其实,关于这个问题有三种种解决方法: ...

  6. 082 HBase的几种调优(GC策略,flush,compact,split)

    一:GC的调优 1.jvm的内存 新生代:存活时间较短,一般存储刚生成的一些对象 老年代:存活时间较长,主要存储在应用程序中生命周期较长的对象 永久代:一般存储meta和class的信息 2.GC策略 ...

  7. macos 下通过sublime text 3 + gosublime+sublimegdb 开发注意事项

    1.macos系统10.13.4下 安装gdb8.0可以正常调试,而gdb8.1不能正常调试,需要跳过这个坑 2.需要对gdb 8.0进行软件签名 3.通过gosublime 运行(cmd+b),添加 ...

  8. 一个垃圾的Android权限框架

    一个垃圾的Android权限框架 学习和参考 简书 https://www.jianshu.com/p/2324a2bdb3d4 写在前头 今天突发奇想想要把Android申请权限的流程封装一下,为使 ...

  9. grpc 使用总结

    1.grpc支持多种语言,需要根据pb文件创建出相应java文件. 2.构建服务端. 3.构建客户端. 4.grpc对象基于创建者模式.

  10. BZOJ.4817.[SDOI2017]树点涂色(LCT DFS序 线段树)

    题目链接 操作\(1.2\)裸树剖,但是操作\(3\)每个点的答案\(val\)很不好维护.. 如果我们把同种颜色的点划分到同一连通块中,那么向根染色的过程就是Access()! 最初所有点间都是虚边 ...