[Functional Programming] From simple implementation to Currying to Partial Application
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的更多相关文章
- Currying vs Partial Application
柯里化相当于函数重构: 偏函数相当于函数适配. So, what is the difference between currying and partial application? As we s ...
- [Functional Programming] Write simple Semigroups type
An introduction to concatting items via the formal Semi-group interface. Semi-groups are simply a ty ...
- [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 ...
- 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 without Lambda - Part 2 Lifting, Functor, Monad
Lifting Now, let's review map from another perspective. map :: (T -> R) -> [T] -> [R] accep ...
- Beginning Scala study note(4) Functional Programming in Scala
1. Functional programming treats computation as the evaluation of mathematical and avoids state and ...
- 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 ...
- Functional programming
In computer science, functional programming is a programming paradigm, a style of building the struc ...
- 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 ...
随机推荐
- 【mysql】一个很小但很影响速度的地方
如果要插入一大批数据,千万不要一条一条的execute, commit.而应该是先全部execute,最后统一commit!!! 千万注意,时间差距还是很大的!! 正确示范:快 ): sql = &q ...
- tomcat 输入学习
Tomcat学习—Tomcat7 修改/webapps/ROOT发布路径(Linux和windows环境) https://blog.csdn.net/u010648555/article/detai ...
- php正则表达式验证(邮件地址、Url地址、电话号码、邮政编码)
1.电子邮件地址的校验 <?php /* 校验邮件地址*/ function checkMail($email) { //用户名,由“w”格式字符.“-”或“.”组成 $email_name= ...
- PHP 中解析 url 并得到 url 参数
这里介绍两种对url操作的方法: 1.拿到一个完整url后,如何解析该url得到里面的参数. /** * 解析url中参数信息,返回参数数组 */ function convertUrlQuery($ ...
- canvas百分百特效
这个特效是别的人,非原创.原创地址 http://blog.csdn.net/lecepin/article/details/53536445 背后的水是可以动的 代码我再研究了下,下面是加了注释的代 ...
- 【AtCoder】AISing Programming Contest 2019
本来以为是1199rated的..仔细一看发现是1999,所以就做了一下 这场涨分很轻松啊...为啥又没打 等pkuwc考完我一定打一场atcoder(咕咕咕,咕咕咕,咕咕咕咕咕咕咕~) 但是其实我思 ...
- 【AtCoder】KEYENCE Programming Contest 2019
A - Beginning 这个年份恐怕需要+2 #include <bits/stdc++.h> #define fi first #define se second #define p ...
- web网页练习
一. HTML部分 1. XHTML和HTML有什么区别 HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的置标语言最主要的不同: XHTML 元素必须被正确地嵌套. XHTML 元 ...
- HTTP 的长连接和短连接
一.什么是长连接 HTTP1.1规定了默认保持长连接(HTTP persistent connection ,也有翻译为持久连接),数据传输完成了保持TCP连接不断开(不发RST包.不四次握手),等待 ...
- Scrapy项目结构分析和工作流程
新建的空Scrapy项目: spiders目录: 负责存放继承自scrapy的爬虫类.里面主要是用于分析response并提取返回的item或者是下一个URL信息,每个Spider负责处理特定的网站或 ...