Scala Learning(4): Currying柯里化的推演

简介:

本文展示加法和乘法的两个例子,最后使用MapReduce的思想把两者统一成一个带Currying的表达形式。

从high-order functions推演到Currying

原始方法

def sum(f: Int => Int, a: Int, b: Int): Int =
  if (a > b) 0
  else f(a) + sum(f, a + 1, b)

表示从a到b,把每个int做一次f处理,把所有结果累加起来。

对应”加法”、”立方”、”阶乘”,实现三个funtion

def id(x: Int): Int = x
def cube(x: Int): Int = x * x * x
def fact(x: Int): Int = if (x == 0) 1 else fact(x - 1)

把这三个方法填充到原始的sum方法里,得到三个新方法

def sumInts(a: Int, b: Int) = sum(id, a, b)
def sumCubes(a: Int, b: Int) = sum(cube, a, b)
def sumFactorials(a: Int, b: Int) = sum(fact, a, b)

将前两个简化,把function匿名地传入sum里,得到

def sumInts(a: Int, b: Int) = sum(x => x, a, b)
def sumCubes(a: Int, b: Int) = sum(x => x * x * x, a, b)

写起来更简短一些。

进一步的,我们注意到a: Int,b: Int这俩参数在各个实现里都是从左到右带过去的,可以简化地重新实现原始的sum方法

def sum(f: Int => Int): (Int, Int) => Int = {
  def sumF(a: Int, b: Int): Int =
    if (a > b) 0
    else f(a) + sumF(a + 1, b)
  sumF
}

如此,新的sum方法传入一个f,返回值也是一个function,借助新的sum,上面三个方法可以这样实现

def sumInts = sum(x => x)
def sumCubes = sum(x => x * x * x)
def sumFactorials = sum(fact)

使用如

sumCubes(1, 10) + sumFactorials(10, 20)

本质上就是Currying的形式了,展开是:

def sum(f: Int => Int)(a: Int, b: Int): Int = ...

类型是什么呢?
类型是

(Int => Int) => (Int, Int) => Int

右侧也就是Int,即

Int => Int => Int

Int => (Int => Int)

MapReduce例子

回到加法的例子:

MapReduce例子

回到加法的例子,用Currying的方式改写为:

def sum(f: Int => Int)(a: Int, b: Int): Int =
  if (a > b) 0
  else f(a) + sum(f)(a + 1, b)

用Currying类似写一个乘法:

def product(f: Int => Int)(a: Int, b: Int): Int =
  if (a > b) 1
  else f(a) * product(f)(a + 1, b)

注意到,两者在初始值、else分支的计算处理上有所不同,使用MapReduce的思想把两个计算统一起来:

def mapReduce(f: Int => Int, combine: (Int, Int) => Int, initValue: Int)(a: Int, b: Int) : Int = 
  if (a > b) initValue
  else combine(f(a), mapReduce(f, combine, initValue)(a+1, b))

把product套进去,可以表示为

def product(f: Int => Int)(a: Int, b: Int): Int =
  mapReduce(f, (x, y) => x*y, 1)(a, b)

把sum套进去,可以表示为

def sum(f: Int => Int)(a: Int, b: Int): Int =
  mapReduce(f, (x, y) => x+y, 0)(a, b)

全文完 :)

目录
相关文章
|
3月前
|
编译器 Scala
scala-柯里化、隐式转换、泛型、upperbound、viewbound、contextBound
scala-柯里化、隐式转换、泛型、upperbound、viewbound、contextBound
22 0
|
Scala
第6关:Scala函数柯里化和闭包
第6关:Scala函数柯里化和闭包
147 0
第6关:Scala函数柯里化和闭包
|
SQL 消息中间件 分布式计算
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
902 0
如何查看spark与hadoop、kafka、Scala、flume、hive等兼容版本【适用于任何版本】
|
3月前
|
分布式计算 资源调度 Java
Scala+Spark+Hadoop+IDEA实现WordCount单词计数,上传并执行任务(简单实例-下)
Scala+Spark+Hadoop+IDEA实现WordCount单词计数,上传并执行任务(简单实例-下)
37 0
|
3月前
|
分布式计算 Hadoop Scala
Scala +Spark+Hadoop+Zookeeper+IDEA实现WordCount单词计数(简单实例-上)
Scala +Spark+Hadoop+Zookeeper+IDEA实现WordCount单词计数(简单实例-上)
32 0
|
4月前
|
SQL 存储 分布式计算
在scala中使用spark
在scala中使用spark
198 0
|
4月前
|
分布式计算 Java Scala
spark 与 scala 的对应版本查看、在idea中maven版本不要选择17,弄了好久,换成11就可以啦
spark 与 scala 的对应版本查看、.在idea中maven版本不要选择17,弄了好久,换成11就可以啦
295 2