Skip to content

Instantly share code, notes, and snippets.

@bhargavg
Last active April 4, 2016 18:23
Show Gist options
  • Save bhargavg/66d77a8b162740bc70999de3a9376389 to your computer and use it in GitHub Desktop.
Save bhargavg/66d77a8b162740bc70999de3a9376389 to your computer and use it in GitHub Desktop.
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