JSON mapping and reader monad [DRAFT]

Functional JSON mapping became a hot theme recently. Clear declarative syntax backed by cryptic concepts of monads and applicative functors has exploded many heads.
I’d like to talk about a little refinement of our mapping pattern to better isolate mapping algorithms from actual data.

Let’s start with some simple mapping code:

struct User {
let name: String
let age: Int

static func build(name: String)(age: Int) -> User {
    return User(name: name, age: age)
}

}

// TODO: write operators

let JSON = [“name”: “Sergei”, “age”: 30]
let user = User.build >> stringForKey(JSON, “name”)
>>> intForKey(JSON, “age”)

The thing that bothers me is coupling of input JSON with our mapping logic. What if we could rectify our mapping to remove this dependency?

Let’s introduce a Reader monad. The simple idea behind is expressing our computation as a function of our JSON parameter and once we need it, “running” it bound with data.

struct Reader {
let value: T -> U

func run(t: T) -> U {
    return value(t)
}

}

Here we express some value U as a function of T and store it in a type safe manner. Here’s how we use it:

func intForKey(key: String) -> Reader {
return Reader({ $0[key] as? Int })
}

See how our dependency on JSON is extracted and moved somewhere to a future?

Once we redefine our lifting and binding operators for Reader<>, we end up with the same mapping code:

let parse = User.build >> stringForKey(JSON, “name”)
>>> intForKey(JSON, “age”)

The only difference is it returns Reader instead of User?. To get User we need to bind it with JSON:

let user = parse.run(JSON)

This approach greatly facilitated code reuse via enabling to define algorithms instead of plain transforms on data.

 
0
Kudos
 
0
Kudos

Now read this

Facebook iOS Infrastructure talk

I’d like to share this brilliant talk from Facebook regarding their experience in building Facebook app. One of the most important problems for them was to tame model layer performance. As a part of their migration from HTML to native... Continue →