I feel that I must be missing something obvious. Decomposing a list into the head and tail and then recursing over the tail is a standard functional programming technique, y
It turns out that there is a generic solution. You need to add these generic requirements:
<
S : Sliceable where S.SubSlice : Sliceable,
S.SubSlice.Generator.Element == S.Generator.Element,
S.SubSlice.SubSlice == S.SubSlice
>
For the question posted, this gives:
func recurseSeq<
S : Sliceable where S.SubSlice : Sliceable,
S.SubSlice.Generator.Element == Int,
S.SubSlice.SubSlice == S.SubSlice,
S.Generator.Element == Int
>(list: S) -> [Int] {
guard let first = list.first else {
return []
}
let rest = recurseSeq(dropFirst(list))
let next = rest.first ?? 0
return [first + next] + rest
}
Here's a useful generic reduce on any sliceable:
extension Sliceable where
SubSlice : Sliceable,
SubSlice.Generator.Element == Generator.Element,
SubSlice.SubSlice == SubSlice {
func recReduce(combine: (Generator.Element, Generator.Element) -> Generator.Element) -> Generator.Element? {
return self.first.map {
head in
dropFirst(self)
.recReduce(combine)
.map {combine(head, $0)}
?? head
}
}
}
[1, 2, 3].recReduce(+) // 6
I can't take credit for this, the solution was posted on the Apple Development Forums.
It's a shame that the generic requirements are so involved for such a a basic operation - it's hardly intuitive! But I'm glad to have a solution...