func makePerson(name: String) -> (age: Int) -> (status: MaritalStatus) -> (requestIDs: [Int]) -> (address: Address) -> Person { | |
return { age in { status in { requestIDs in { address in | |
Person(name: name, age: age, status: status, requestIDs: requestIDs, address: address) | |
}}}} | |
} | |
func makeAddress(flatNo: String) -> (buildingName: String) -> Address { | |
return { buildingName in | |
Address(flatNo: flatNo, buildingName: buildingName) | |
} | |
} |
func get<T, U>(box:[String: U], key: String) -> T? { | |
return box[key] as? T | |
} |
let json: [String: Any] = [ | |
"name": "Bill", | |
"age": 47, | |
"status": "s", | |
"request_ids": [178, 249, 320, 4481], | |
"address": [ | |
"flat_no": "31/c", | |
"building_name": "Grand Arcade" | |
], | |
] | |
func parseAddress(dict: [String: String]) -> Address? { | |
return makeAddress <*> get(dict, key: "flat_no") | |
<*> get(dict, key: "building_name") | |
} | |
func parseStatus(value: String) -> MaritalStatus? { | |
switch value { | |
case "s": | |
return .Single | |
case "m": | |
return .Married | |
default: | |
return .None | |
} | |
} | |
func parsePerson<T>(dict: [String: T]) -> Person? { | |
return makePerson <*> get(dict, key: "name") | |
<*> get(dict, key: "age") | |
<*> get(dict, key: "status") <~~ parseStatus | |
<*> get(dict, key: "request_ids") | |
<*> get(dict, key: "address") <~~ parseAddress | |
} | |
print(parsePerson(json)!) |
struct Person { | |
let name: String | |
let age: Int | |
let status: MaritalStatus | |
let requestIDs: [Int] | |
let address: Address | |
} | |
struct Address { | |
let flatNo: String | |
let buildingName: String | |
} | |
enum MaritalStatus { | |
case Married, Single | |
} |
infix operator <*> { | |
associativity left | |
precedence 100 | |
} | |
// Operator that takes | |
// f: An optional function that takes A and returns B | |
// x: An optional value of type A | |
// | |
// and returns f(x) if both f and x are present | |
func <*><A, B>(f: (A -> B)?, x: A?) -> B? { | |
guard let f = f, x = x else { | |
return nil | |
} | |
return f(x) | |
} | |
infix operator <~~ { | |
associativity left | |
precedence 110 // higher than <*> precedence | |
} | |
// Operator that takes | |
// x: Optional value of type A | |
// f: Transformation function that maps from | |
// A to an Optional B (because the transformation can fail) | |
// | |
// and returns f(x) if x is present (applies the transformation) | |
func <~~<A, B>(x: A?, f: (A -> B?)) -> B? { | |
guard let x = x else { | |
return .None | |
} | |
return f(x) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment