Generics and Functional programming in Swift -
the 2 variants of sum function below attempt repeat lisp version introduced abelson , sussman in classic "structure , interpretation of computer programs" book in swift. first version used compute sum of integers in range, or sum of squares of integers in range, , second version used compute approximation pi/8.
i not able combine versions single func handle types. there clever way use generics or other swift language feature combine variants?
func sum(term: (int) -> int, a: int, next: (int) -> int, b: int) -> int { if > 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 > b { return 0 } return (term(a) + sum(term, next(a), next, b)) }
with
sum({$0}, 1, {$0 + 1}, 3)
6 result
sum({$0 * $0}, 3, {$0 + 1}, 4)
25 result
8.0 * sum({1.0 / float(($0 * ($0 + 2)))}, 1, {$0 + 4}, 2500)
3.14079 result
to make bit easier have changed method signatures , assume enough work func sum_ <t> (term: (t -> t), a: t, next: (t -> t), b: t) -> t {
, t kind of number.
unfortunately there no number
type in swift, need make our own. our type needs support
- addition
- comparison
0
(the neutral element addition)
new protocols requirements of function
comparison handled in comparable
protocol, reset can create our own protocols:
protocol neutraladditionelementprovider { class func neutraladditionelement () -> self } protocol addable { func + (lhs: self, rhs: self) -> self }
sum
implementation
we can implement sum
function:
func sum <t t:addable, t:neutraladditionelementprovider, t:comparable> (term: (t -> t), a: t, next: (t -> t), b: t) -> t { if > b { return t.neutraladditionelement() } return term(a) + sum(term, next(a), next, b) }
making int
, double
conform protocols
+
implemented double
, int
protocol conformance easy:
extension double: addable {} extension int: addable {}
providing neutral element:
extension int: neutraladditionelementprovider { static func neutraladditionelement() -> int { return 0 } } extension double: neutraladditionelementprovider { static func neutraladditionelement() -> double { return 0.0 } }
Comments
Post a Comment