Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Atry/220227cd6ce48ae49280 to your computer and use it in GitHub Desktop.
Save Atry/220227cd6ce48ae49280 to your computer and use it in GitHub Desktop.

Need help: naming for a new library that creates scalar monadic expressions

Hello, all,

We, some people from ThoughtWorks China, have created a macro library that converts native imperative syntax to scalaz's monadic expression. But, before we release the first version of this library, we found a very tough problem: what is the best name for the project, the source file and the methods.

Current situation

Currently, our project is named scalaz-monad-factory. I guess the name is inappropriate, because this project does not create monads, instead, it uses scalaz's monad to create functional expressions.

The current usage is very simple:

import scalaz.std.list._

val transformer = com.thoughtworks.scalazMonadFactory.Transformer[List]

val list1 = List("foo", "bar", "baz")
val list2 = List("Hello", "World!")

val concatList = transformer.async(transformer.await(list1).substring(0, 2) + " " + transformer.await(list2).substring(1, 4))

Assert.assertEquals(List("fo ell", "ba ell", "ba ell", "fo orl", "ba orl", "ba orl"), concatList)

The method transformer.async is a macro and transformer.await is a fake method to fetch the result of a monadic value. You can put any Scala expressions in the async macro and it will magically turn your code into monadic expressions. You can visit the test cases for more information

So, the code val concatList = transformer.async(transformer.await(list1).substring(0, 2) + " " + transformer.await(list2).substring(1, 4)) will be translated to monadic expression:

val concatList = Monad[List].bind(list2) { (string2: String) =>
  Monad[List].map(list1) { (string1: String) =>
    string1.substring(0, 2) + " " + string2.substring(1, 4)
  }
}

Which also equals to list comprehension supported by Scala Standard Library:

val concatList = for {
  string1 <- list1
  string2 <- list2
} yield (string1.substring(0, 2) + " " + string2.substring(1, 4))

Currently, the await method is implicit, so we can also write like this:

import transformer._
val concatList = async(list1.substring(0, 2) + " " + list2.substring(1, 4))

The name for the macro

async

Everything is good until now, except the macro name async.

async is a C# 4.5 keyword to perform CPS transformation. When our macro works with some kind of Cont monad, it will do the same thing as C# async, but it also cooperates well with other monads, e.g. IO monad, Option monad, and List monad shown before. So I think the name should be more general than async.

do

Another candidate name for the macro is do, because there is a similiar do notation in Haskell. Unfortunately do is a keyword in Scala, so we must quoted it like this:

val concatList = transformer.`do`(transformer.await(list1).substring(0, 2) + " " + transformer.await(list2).substring(1, 4))

apply

I also thought about simply use apply as the macro name, this will allow users treating transformer itself as a function:

val concatList = transformer(transformer.await(list1).substring(0, 2) + " " + transformer.await(list2).substring(1, 4))

Other candidates

Other candidate names are: monadic, transform

The name for the fake method, currently named await

await

In C# 4.5, await is a keyword to wait a Task, which must be nested in a async method. Our Transformer.await, which is used to get the result from a monadic value, evaluates immediately for Option monad and List monad, and may only blocking wait for IO monad or other asynchronous monads. So it is also good to have a more general name.

<-

<- is the syntax in Haskell. Haskell's x <- action corresponds to current val x = transformer.await(action) in our project. Unfortunately <- is a keyword in Scala, so we must quoted it like this:

val concatList = transformer.`do`(transformer.`<-`(list1).substring(0, 2) + " " + transformer.`<-`(list2).substring(1, 4))

This is a less annoying problem than do, because we may use implicit call for most time.

Postfix method

Another option is providing a implicit class with a postfix await method, so we can write action.await. This syntax is less trivial than transformer.await(action), and also more explicit and more clear than implicit calls.

Survey

I created a survey to gather your opinion: https://jinshuju.net/f/TUZeAO.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment