As a personal project, I am writing yet another Scala library for DynamoDb. It contains many interesting aspect such as reading and writing from an AST (just as Json), handling HTTP request, streaming data…

In order to be able able to communicate with DynamoDb, one needs to be able to read from / to the DynamoDb format (the “AST”). I extracted this reading / writing from / to the AST in a minimalist library: dynamo-ast . It contains two main type classes: DynamoReads[_] and DynamoWrites[_] (deeply inspired from Play Json).

I successfully coded the reading part of the library ending with a very simple code such as :

trait DynamoRead[A] { self => def read(dynamoType: DynamoType): DynamoReadResult[A] } case class TinyImage(url: String, alt: String) val dynamoReads: DynamoReads[TinyImage] = { for { url <- read[String].at(“url”) alt <- read[String].at(“alt”) } yield (url, alt) map (TinyImage.apply _).tupled } dynamoReads.reads(dynamoAst) //yield DynamoReadResult[TinyImage]

At that point, I thought I wrote the most complicated part of the library and the DynamoWrite[_] part would be a piece of cake. I am however stuck on writing the DynamoWrite part. I was a fool.

My goal is to provide a very similar “user experience” with the DynamoWrite[_] and keep it as simple as possible such as :

val dynamoWrites: DynamoWrites[TinyImage] = { for { url <- write[String].at(“url”) alt <- write[String].at(“alt”) } yield (url, alt) map (TinyImage.unapply _) //I am not sure what to yield here nor how to code it } dynamoWrites.write(TinyImage(“http://fake.url”, “The alt desc”)) //yield DynamoWriteResult[DynamoType]

Since this library is deeply inspired from Play Json library (because I like its simplicity) I had a look at the sources several times. I kind of dislike the way the writer part is coded because to me, it adds a lot of overhead (basically each time a field a written, a new JsObject is created with one field and the resulting JsObject for a complete class is the merge of all the JsObjects containing one field).

From my understanding, the DynamoReads part can be written with only one trait ( DynamoRead[_] ). The DynamoWrites part however requires at least two such as :

trait DynamoWrites[A] { def write(a: A): DynamoWriteResult[DynamoType] } trait DynamoWritesPath[A] { def write(path:String, a: A): DynamoWriteResult[(String, DynamoType)] }

The DynamoWrites[_] is to write plain String, Int… and the DynamoWritesPath[_] is to write a tuple of (String, WhateverTypeHere) (to simulate a “field”).

So writing write[String].at(“url”) would yield a DynamoWritesPath[String] . Now I have several issues :

I have no clue how to write flatMap for my DynamoWritesPath[_]

what should yield a for comprehension to be able to obtain a DynamoWrite[TinyImage]

What I wrote so far (totally fuzzy and not compiling at all, looking for some help on this). Not committed at the moment (gist): https://gist.github.com/louis-forite/cad97cc0a47847b2e4177192d9dbc3ae

To sum up, I am looking for some guidance on how to write the DynamoWrites[_] part. My goal is to provide for the client the most straight forward way to code a DynamoWrites[_] for a given type. My non goal is to write the perfect library and keep it a zero dependency library.

Link to the library: https://github.com/louis-forite/dynamo-ast