Personal Log »

A wiki and Tagless Final

I’m still refreshing my Go, and my friend Oscar is meeting Go for first time. Having a chat, I proposed him a possible project that could be interesting to have something to work on as he learns. Because learning to program a new language requires programming on that language, and for that, you most likely need a project.

I guess it could have been a blog as well –and I know it because I wrote my own blog engine in PHP, Perl and Python–, but I contributed a spec and Oscar is working on wikingo now based on that.

Looking at Oscar’s code, last weekend I thought: why not give it a go using Scala and some of the tools I work with at my day job but I never have time to do other things with?

So I wrote a toy wiki with Scala, http4s, doobie, ScalaTags and CommonMark (to render the Markdown), and using Tagless Final pattern –some context in the Expression Problem, and I haven’t found a “good” resource to link–.

Tagless Final is a pattern in functional programming, and is just an abstraction to build software, in which you define a Domain Specific Language (DSL) using Algebraic Data Types (or ADT, for example: a generic trait with abstract methods), and then provide an implementation (also called interpreter).

// my DSL
trait Wiki[F[_]] {
  type R = TypedTag[String]

  def init: F[Unit]
  def getPage(id: String): F[Option[R]]
  def editPage(id: String): F[Option[R]]
  def savePage(id: String, body: String): F[Int]
  def searchPage(query: String): F[R]
}

And this is relevant because http4s is built on top of Cats, which is a library for functional programming in Scala borrowing ideas from the Haskell programming language, and supports Tagless Final nicely.

Anyway, if what I have written so far doesn’t transmit the idea that is complicated, let me tell you: it is!

My expectations was to put together something quick and easy, but I got myself stuck in the same problems I have often encountered in my day job.

Some notes:

  • Missing documentation and examples –if you are trying to do something not in the docs, it isn’t easy to discover things yourself–. This was specially painful when trying to decode the form data: I was missing an implicit, and even looking at the examples, I didn’t see that my type F was asking for Sync but I really needed Asyncfacepalm–.
  • Because I decided to use H2 as database, I got stuck a couple of times with doobie –always my fault, if you use H2 as an in memory database, remember to set DB_CLOSE_DELAY=-1 in your connection properties, or your DB will be wiped mysteriously–.
  • I got stuck finding a mapping for Java’s LocalDateTime in doobie, even if I knew there has an implicit somewhere. The answer is deep down in the FAQ, instead of being included in the part of the docs that deals with mappings.
  • Turns out there aren’t many current Markdown to HTML libraries, CommonMark works fine –although it is a Java one–.

The end result looks very nice. Is not that different from a Model View Controller pattern: Wiki provides a description of the controller, with implementation in impl. It calls the models –implemented with SQL in WikiSql–, and maps to the views in WikiTemplates. WikiServer has the router that calls the controller. Concise yet very readable.

So I didn’t dislike the result, but oh it was hard to get there!

Would you like to discuss the post? You can send me an email!