ListK provides lazy lists like ones in functional programming for Swift.
let xs: List<Int> = [2, 3, 5, 7, 11]
let infinite: List<Int> = List { $0 } // [0, 1, 2, 3, 4, ...]
let mapped: List<Int> = infinite.map { $0 * $0 } // [0, 1, 4, 9, 16, ...]
let taken: List<Int> = infinite.take(5) // [0, 1, 2, 3, 4]
let dropped: List<Int> = infinite.drop(5) // [5, 6, 7, 8, 9, ...]
// Pattern matching with `head` and `tail`
func sum(xs: List<Int>) -> Int {
switch xs {
case .None: return 0
case let .Some(x, xs): return x + sum(xs())
}
}
// Operators compatible with thoughtbot/Runes
let ys: List<Int> = infinite >>- { $0 % 2 == 0 ? [$0] : [] } // [0, 2, 4, 6, 8, ...]
let zs: List<Int> = curry(*) <^> [2, 3] <*> [5, 7] // [10, 14, 15, 21]
// Fibonacci
func fibonacci() -> List<Int> {
return List(initial: [0, 1], next: sum)
} // returns [0, 1, 1, 2, 3, 5, 8, 13, ...]
- Lazy evaluation
- Pattern matching with
head
andtail
- Operators compatible with thoughtbot/Runes
- Nested
reduceRight
with lazy evaluation
Because List
is evaluated lazily, operations for whole lists, map
, filter
and so on, can be applied to infinite lists.
let xs: List<Int> = List { $0 } // [0, 1, 2, 3, 4, ...]
let mapped: List<Int> = xs.map { $0 * $0 } // [0, 1, 4, 9, 16, ...]
It is a typical operation to matching a list to head
and tail
in functional programming.
-- Haskell
sum :: [Integer] -> Integer
sum [] = 0
sum (x:xs) = x + sum xs
List
of ListK can be matched head
and tail
because it is declared as enum
.
enum List<Element> {
case None
case Some(Element, () -> List<Element>)
}
The following code is direct porting sum
to Swift.
func sum(xs: List<Int>) -> Int {
switch xs {
case .None: return 0
case let .Some(x, xs): return head + sum(tail())
}
}
Operators declared in thoughtbot/Runes are available.
let ys: List<Int> = infinite >>- { $0 % 2 == 0 ? [$0] : [] } // [0, 2, 4, 6, 8, ...]
let zs: List<Int> = curry(*) <^> [2, 3] <*> [5, 7] // [10, 14, 15, 21]
Nested reduceRight
is still lazily evaluated.
let xss: List<List<Int>> = List { List(repeatedValue: $0, count: $0) }
// [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], ...]
let flattened: List<Int> = xss.reduceRight(List<Int>()) { xs, flattened in
xs.reduceRight(flattened()) { x, flattened in
List(head: x, tail: flattened())
}
} // [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, ...]
# Cartfile
github "koher/ListK" ~> 0.2