【scala函数式编程】函数式编程实现

常见函数式编程操作

几行代码展示常见函数式编程操作

1. 高阶函数:以函数为参数的函数

def formatAbs(n : Int) : String = { s"${n}'s abs is ${Math.abs(n)}" }
def formatSquare(n : Int) : String = { s"${n}'s abs is ${n*n}" }
def formatResult(n : Int, f : Int=>String) : String = { f(n) } 

2. 多态函数:使用泛型标记变量类型或返回值类型

def formatAbs(n : Int) : String = { s"${n}'s abs is ${Math.abs(n)}" }
def formatSquare(n : Int) : String = { s"${n}'s abs is ${n*n}" }
def formatResult[A](n : A, f : A =>String) : String = { f(n) } 

3. 通过高阶函数实现柯里化:

def func(a:Int, b:Int):String= s"$a + $b"
def curryFunc[A, B](f : (A , A) =>B) : A => A=> B = {(a:A) => (b : A) => f(a, b)}
val test = curryFunc(1, func)

4. 通过高阶函数实现反柯里化:

def func(a:Int)(b:Int):String = s"$a + $b"
def uncurryFunc[A, B](f : A => A => B) : (A, A) => B = {(a : A , b : A) => f(a)(b)}
val test = uncurryFunc(func)

注意: =>是右结合的,例如柯里化函数 A => B => C,等价于A => (B => C)

5. 补充:柯里化函数

def func(a: Int)(b: Int):String = s"$a + $b"
val func: Int => Int => String = (a: Int) => (b: Int) => s"$a + $b":String
val func1 = func(1) _

6. 补充:简单函数

val func:() => String = () =>  "测试":String
val result = func()

7. 补充:函数的定义与类型表达式

类型表达:(Int, Int) => Int // 类型表达式中不能出现任何变量,只能出现类型
代数表达:(x:Int, y:Int) => x + y或者(x:Int, y:Int) => x + y :Int // 代数表达式中的左侧,所有类型的位置都必需指定变量名称,右侧只能出现一种类型,且不用对计算过程加小括号

8.补充:根据函数签名一步一步实现多态函数

函数由函数名、参数变量、参数类型、返回类型、函数体组成,函数签名就是除函数体以外的函数头

例子1:简单例子

类型表达式转换为代数表达式:def partiall[A,B,C](a: A, f:(A,B) => C): B => C 

在返回类型中,从右向左依次来看,所有=>右侧的类型最终完善为函数表达式,所有=>左侧的类型最终构成函数参数
a. 使用参数列表中=>左侧的类型替换返回类型=>右侧的类型,完善函数表达式:[函数名](类型列表),需要将C替换为=>左侧推导结果为C的表达式,根据左侧参数类型,我们得知f:(A,B) => C,根据引用透明替换为f(A,B)
b. 对=>左侧的类型,若无小括号则使用小括号包裹,构成参数列表:(类型列表),每有一个=>都会对应一个独立的类型列表,这里需要将B替换为(B)
c. 重复上述过程,直至所有出现在返回类型=>右侧的类型完全被参数列表中仅出现在=>左侧的类型替换为止
d. 对所有类型指定变量名:变量名:变量类型,例如,替换B为b: B或b

代数替换:def partiall[A,B,C](a: A, f:(A,B) => C): B => C = (B) => f(A, B)
类型替换:def partiall[A,B,C](a: A, f:(A,B) => C): B => C = (b: B) => f(a: A, b: B)
简写为:def partiall[A,B,C](a: A, f: (A,B) => C): B => C = (b) => f(a, b)
简写为:def partiall[A,B,C](a: A, f:(A,B) => C): B => C = b => f(a, b) // 当省略类型时,参数列表的小括号也可以省略

例子2:柯里化

类型表达式转换为代数表达式:def curry[A,B,C](f:(A,B) =>C):A => (B => C)

在返回类型中,从右向左依次来看:
a. C出现在=>的右侧,必需替换为为函数表达式,根据引用透明,C可以由f:(A,B) =>C推导得出,完善函数表达式:函数名,因此替换为f(A, B)
b. B仅出现在=>左侧,构成一个参数列表,因此替换为(B)
c. A仅出现在=>左侧,构成另一个参数列表,因此替换为(A)
d. 对所有类型指定变量名:变量名:变量类型,例如,替换B为b:B或b

代数替换:def curry[A,B,C](f:(A,B) =>C):A => (B => C) = (A) => (B) => f(A, B)
类型替换:def curry[A,B,C](f:(A,B) =>C):A => (B => C) = (a:A) => (b:B) => f(a:A, b:B)
简写为:def curry[A,B,C](f:(A, B) => C): A =>(B => C) = (a) => (b) => f(a, b)
简写为:def curry[A,B,C](f:(A, B) => C): A =>(B => C) = a => b => f(a, b)

例子3:反柯里化

类型表达式转换为代数表达式:def uncurry[A,B,C](f: A => B => C):(A,B) => C

在返回类型中,从右向左依次来看:
a. C出现在=>右侧,必需替换为函数表达式,根据引用透明,C可以由f:A => B => C推导得出,完善函数表达式:函数名,有两个=>分别对应两个参数列表,因此替换为f(A)(B)
b. (A,B)仅出现在=>左侧,构成参数列表,由于已经有了小括号,因此保持不变为(A, B)
c. 对所有类型指定变量名:变量名:变量类型,例如,替换A为a:A,替换B为b:B

代数替换:def uncurry[A,B,C](f: A => B => C):(A,B) => C = (A, B) => f(A)(B)
类型替换:def uncurry[A,B,C](f: A => B => C):(A,B) => C = (a:A, b:B) => f(a:A)(b:B)
简写为:def uncurry[A,B,C](f: A => B => C):(A,B) => C = (a, b) => f(a)(b) // 多参数列表时,括号不能省略

例子4: 函数嵌套

类型表达式转换为代数表达式:def compose[A,B,C](f: B => C, g: A => B): A => C

在返回类型中,从右向左依次来看:
a. C出现在=>右侧,必需替换为函数表达式,根据引用透明,C可以由f: B => C推导得出,完善函数表达式:函数名,有一个=>对应一个参数列表,因此替换为f(B)
b. A仅出现在=>左侧,使用小括号包裹,构成参数列表,因此替换为(A)
c. 此时代数表达式为:def compose[A,B,C](f: B => C, g: A =>B): A => C = (A) => f(B),此时参数A和函数表达式B不一致,因此仍需进一步代数替换,重复a、b过程
d. B出现在=>右侧,必需替换为函数表达式,根据引用透明,B可以由g: A => B推导得出,完善函数表达式:函数名,有一个=> 对应一个参数列表,因此替换为g(A)

代数替换:def compose[A,B,C](f: B => C, g: A => B): A => C = (A) => f(B)
继续替换:def compose[A,B,C](f: B => C, g: A => B): A => C = (A) => f(g(A))
类型替换:def compose[A,B,C](f: B => C, g: A => B): A => C = (a: A) => f(g(a: A))
等效为:def compose[A,B,C](f: B => C, g: A => B): A => C = (a: A) => f(g(a: A):B):C
简写为:def compose[A,B,C](f: B => C, g: A => B): A => C = (a) => f(g(a))
简写为:def compose[A,B,C](f: B => C, g: A => B): A => C = a => f(g(a))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼摆摆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值