1. Fetch data from Github
extension URLSession {
func dataTask(
with url: URL,
completionHandler:
@escaping (Data?, URLResponse?, Error?) -> Void
) -> URLSessionDataTask
}
Slide 46
Slide 46 text
1. Fetch data from Github
completionHandler
=> Future
(Data?, URLResponse?, Error?)
=> Result
Future>
Slide 47
Slide 47 text
2. Deserialize
Response is a JSON object in form of an array of repos:
[
{
“name”: “repo_name”,
...
},
...
deserialize: (Data) throws -> [Data]
throws -> [Repo]
1. Create protocol
protocol ValidatedType {
associatedtype PA
associatedtype PE
}
extension Validated: ValidatedType {
typealias PA = A
typealias PE = E
}
Slide 70
Slide 70 text
2. Duplicate API in protocol (return concrete type)
protocol ValidatedType {
associatedtype PA
associatedtype PE
func map(_ f: (PA) -> B) -> Validated
}
extension Validated: ValidatedType {}
Slide 71
Slide 71 text
3. Implement the nested method in a constrained extension
extension Future where A: ValidatedType {
func map(
_ f: @escaping (A.PA) -> B
) -> Future> {
return map { $0.map(f) }
}
}
Slide 72
Slide 72 text
Method-based
1. Generalize the method,
not extension
2. Add constraints to
the method, not extension
Slide 73
Slide 73 text
1. Generalize the method, not extension
extension Future {
func map(
_ f: @escaping (VA) -> B
) -> Future> {
// work in progress
}
}
Slide 74
Slide 74 text
2. Add constraints to the method, not extension
extension Future {
func map(
_ f: @escaping (VA) -> B
) -> Future>
where A == Validated {
return map { $0.map(f) }
}
}
Slide 75
Slide 75 text
!"
Slide 76
Slide 76 text
Now we can filter Swift repos!
let repos: Future<
Validated<
Array,
Either
>> = githubClient.fetch(.repos, for: user)
.map { deserialize($0) }
.{ // transforms described before }
repos.filter { (repo: Repo) -> Bool in
repo.language == “Swift”
} // it works!
Slide 77
Slide 77 text
No content
Slide 78
Slide 78 text
Use code generation
Please see this great talk for details:
Elviro Rocca — Protocol-Oriented Monad Transformers
https://www.youtube.com/watch?v=Zmb86zblcto
Slide 79
Slide 79 text
Use “wide”
containers,
like Observable
Slide 80
Slide 80 text
Future< <== observable is async
Validated< <== observable can return error
Array< <== observable is sequence
Repo
>,
Either
>
>
Observable <- but some information will be lost!