泛型和Swift中的函数式编程 [英] Generics and Functional programming in Swift

查看:114
本文介绍了泛型和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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆