泛型和Swift中的函数式编程 [英] Generics and Functional programming in Swift
问题描述
以下sum函数的两个变体是我试图重复Abelson和Sussman在Swift中经典的计算机程序结构和解释一书中介绍的lisp版本。第一个版本用于计算范围内整数的总和,或一个范围内整数的平方和,第二个版本用于计算pi / 8的近似值。
我无法将这些版本合并为一个可处理所有类型的func。
有没有一种巧妙的方法来使用泛型或其他Swift语言功能来组合变体? func sum(term:(Int) - > Int,a:Int,next:(Int) - > Int,b:Int) - > Int {
如果a> b(
return 0
)
return(term(a)+ sum(term,next(a),next,b))
}
)func sum(term:(Int) - > Float,a:Int,next:(Int) - > Int,b:Int) - >浮动{
如果a> b(
return 0
)
return(term(a)+ sum(term,next(a),next,b))
}
with
sum({$ 0},1,{$ 0 + 1},3)
6作为结果
sum({$ 0 * $ 0},3,{$ 0 + 1},4 )
25结果
/ code> 3.14079结果
解决方案 <为了使它更容易一些,我稍微更改了方法签名,并假定它足够用于处理 func sum_< T> (项:(T→T),a:T,下一项:(T→T),b:T)→> T {
,其中T是某种数字。
不幸的是,没有 Number
>输入Swift,所以我们需要自己创建。我们的类型需要支持
- 加法
- 比较
-
0
(用于添加的中性元素)
需求的新协议的函数
比较在 Comparable
协议中处理,对于重置,我们可以创建自己的协议:
协议NeutralAdditionElementProvider {
class func neutralAdditionElement() - > Self
}
协议可添加{
func +(lhs:Self,rhs:Self) - > Self
}
sum
执行
现在我们可以实现 sum
函数:
func sum< T其中T:可加,T:中性加法元素提供者,T:可比> (项:(T→T),a:T,下一项:(T→T),b:T)→> T {
如果a> b {
return T.neutralAdditionElement()
}
退货期限(a)+总额(期限,下一个(a),下一个,b)
}
制作 Int
和 Double
符合协议
+
已经为 Double code>和 Int
因此协议一致性很简单:
扩展名Double:Addable {}
扩展名Int:可添加{}
提供一个中性元素:
扩展名Int:NeutralAdditionElementProvider {
static func neutralAdditionElement() - > Int {
return 0
}
}
扩展名Double:NeutralAdditionElementProvider {
static func neutralAdditionElement() - > Double {
return 0.0
}
}
The two variants of the sum function below are my attempt to repeat the lisp version introduced by Abelson and Sussman in the classic "Structure and interpretation of Computer Programs" book in Swift. The first version was used to compute the sum of integers in a range, or the sum of squares of integers in a range, and the second version was used to compute the approximation to pi/8.
I was not able to combine to the versions into a single func which will handle all types. Is there a clever way to use generics or some other Swift language feature to combine the variants?
func sum(term: (Int) -> Int, a: Int, next: (Int) -> Int, b: Int) -> Int {
if a > b {
return 0
}
return (term(a) + sum(term, next(a), next, b))
}
func sum(term: (Int) -> Float, a: Int, next: (Int) -> Int, b: Int) -> Float {
if a > b {
return 0
}
return (term(a) + sum(term, next(a), next, b))
}
with
sum({$0}, 1, {$0 + 1}, 3)
6 as result
sum({$0 * $0}, 3, {$0 + 1}, 4)
25 as result
8.0 * sum({1.0 / Float(($0 * ($0 + 2)))}, 1, {$0 + 4}, 2500)
3.14079 as result
解决方案 To make it a bit easier I have changed the method signatures slightly and assume that it is good enough to work for func sum_ <T> (term: (T -> T), a: T, next: (T -> T), b: T) -> T {
, where T is some kind of number.
Unfortunately there is no Number
type in Swift, so we need to make our own. Our type needs to support
- addition
- comparison
0
(the neutral element for addition)
New Protocols for the requirements of the function
Comparison is handled in the Comparable
protocol, for the reset we can create our own protocols:
protocol NeutralAdditionElementProvider {
class func neutralAdditionElement () -> Self
}
protocol Addable {
func + (lhs: Self, rhs: Self) -> Self
}
sum
implementation
We can now implement the sum
function:
func sum <T where T:Addable, T:NeutralAdditionElementProvider, T:Comparable> (term: (T -> T), a: T, next: (T -> T), b: T) -> T {
if a > b {
return T.neutralAdditionElement()
}
return term(a) + sum(term, next(a), next, b)
}
Making Int
and Double
conform to the protocols
+
is already implemented for Double
and Int
so protocol conformance is easy:
extension Double: Addable {}
extension Int: Addable {}
Providing a neutral element:
extension Int: NeutralAdditionElementProvider {
static func neutralAdditionElement() -> Int {
return 0
}
}
extension Double: NeutralAdditionElementProvider {
static func neutralAdditionElement() -> Double {
return 0.0
}
}
这篇关于泛型和Swift中的函数式编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!