Last active
August 29, 2015 14:26
-
-
Save alonecuzzo/1c63bf16b44fb76530ab to your computer and use it in GitHub Desktop.
Code from Functional Presentation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// paperlesspost.com/api/v100/event?id=3948 | |
//{ | |
// id: 3948, | |
// eventName: "The Party For the LOLZ", | |
// hostName: "datFoolCuzzo" | |
// | |
//} | |
protocol JSONDecodable { | |
static func decode(json: JSON) -> Self? | |
} | |
infix operator >>> { associativity left precedence 150 } | |
func >>><A,B>(a: A?, f: A -> B?) -> B? { | |
if let x = a { | |
return f(x) | |
} else { | |
return .None | |
} | |
} | |
func >>><A, B>(a: Result<A>, f: A -> Result<B>) -> Result<B> { | |
switch a { | |
case let .Value(x): return f(x.value) | |
case let .Error(error): return .Error(error) | |
} | |
} | |
//fmap | |
infix operator <^> { associativity left } | |
func <^><A,B>(f: A -> B, a: A?) -> B? { | |
if let x = a { | |
return f(x) | |
} else { | |
return .None | |
} | |
} | |
//apply | |
infix operator <*> { associativity left } | |
func <*><A,B>(f: (A -> B)?, a: A?) -> B? { | |
if let x = a, fx = f { | |
return fx(x) | |
} else { | |
return .None | |
} | |
} | |
typealias JSON = AnyObject | |
typealias JSONDictionary = Dictionary<String, JSON> | |
struct EventDetails: JSONDecodable { | |
let id: Int | |
let eventName: String | |
let hostName: String | |
static func create(id: Int)(eventName: String)(hostName: String) -> EventDetails { | |
return EventDetails(id: id, eventName: eventName, hostName: hostName) | |
} | |
static func decode(json: JSON) -> EventDetails? { | |
return JSONObject(json) >>> { d in | |
EventDetails.create <^> d["id"] >>> JSONInt <*> d["eventName"] >>> JSONString <*> d["hostName"] >>> JSONString | |
} | |
} | |
} | |
//enum Either<A,B> { | |
// case Left(A) | |
// case Right(B) | |
//} | |
final class Box<A> { | |
let value: A | |
init(_ value: A) { | |
self.value = value | |
} | |
} | |
enum Result<A> { | |
case Error(NSError) | |
case Value(Box<A>) | |
init(_ error: NSError?, _ value: A) { | |
if let error = error { | |
self = .Error(error) | |
} else { | |
self = .Value(Box(value)) | |
} | |
} | |
} | |
func JSONInt(object: JSON) -> Int? { | |
return object as? Int | |
} | |
func JSONString(object: JSON) -> String? { | |
return object as? String | |
} | |
func JSONObject(object: JSON) -> JSONDictionary? { | |
return object as? JSONDictionary | |
} | |
//parseResponse | |
struct Response { | |
let data: NSData | |
var statusCode: Int = 500 | |
init(_ data: NSData, urlResponse: NSURLResponse) { | |
self.data = data | |
if let urlResponse = urlResponse as? NSHTTPURLResponse { | |
self.statusCode = urlResponse.statusCode | |
} | |
} | |
} | |
func parseResponse(response: Response) -> Result<NSData> { | |
let validRange = 200..<300 | |
if !contains(validRange, response.statusCode) { | |
return .Error(NSError()) | |
} | |
return .Value(Box(response.data)) | |
} | |
func decodeJSON(data: NSData) -> Result<JSON> { | |
var jsonError: NSError? | |
let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &jsonError) | |
return resultFromOptional(json, jsonError!) | |
} | |
func parseResult<A: JSONDecodable>(data: NSData!, urlResponse: NSURLResponse!, error: NSError!) -> Result<A> { | |
let result = Result(error, Response(data, urlResponse: urlResponse)) | |
return result >>> parseResponse >>> decodeJSON >>> decodeObject | |
} | |
func decodeObject<A: JSONDecodable>(json: JSON) -> Result<A> { | |
return resultFromOptional(A.decode(json), NSError()) | |
} | |
func resultFromOptional<A>(optional: A?, error: NSError) -> Result<A> { | |
if let optional = optional { | |
return .Value(Box(optional)) | |
} else { | |
return .Error(error) | |
} | |
} | |
func getEventDetails<A: JSONDecodable>(request: NSURLRequest, callback: (Result<A>) -> ()) { | |
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, urlResponse, error in | |
callback(parseResult(data, urlResponse, error)) | |
} | |
task.resume() | |
} | |
class FUTURENETWORKING { | |
func foo() { | |
getEventDetails(NSURLRequest()) { (result: Result<EventDetails>) -> Void in | |
switch result { | |
case let .Error(error): | |
break | |
case let .Value(boxedEventDetails): | |
let eventDetails = boxedEventDetails.value | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment