Applicative Functors in Scala
The Applicative Functor pattern is an incredibly powerful abstraction. I recently added it to a branch of Scalaz. However, it would be nice if I could alter the fixity of functions so that the parentheses below are not required to make the expression right-associative.
val add = (a: Int) => (b: Int) => (c: Int) => a + b + c val none: Option[Int] = None // Grrr Scala // Some(24) println(Some(7) <*> (Some(8) <*> (Some(9) > add))) // None println(Some(7) <*> (none <*> (Some(9) > add))) // List(87, 88, 89, 91, 92, 93) println(List(1, 2, 3) <*> (List(77) <*> (List(9, 13) > add)))
Having to write that silly none value is annoying too. At the very least a none function would suffice:
def none[A]: Option[A] = None
That way. I could use none[Int] and be done with it.
Still, this pattern is a nice tool to use and I will surely be using it in the future.
June 20th, 2008 at 12:02 pm
BTW, you can make the definition of *add* a lot more concise with the semantically-equivalent:
def add(a: Int)(b: Int)(c: Int) = a + b + c
Fewer arrows, anyway. Also, if you really need right-associativity, you can suffix your operators with a colon (:). It’s ugly, but it does the trick.
June 20th, 2008 at 12:07 pm
Oh, if you use right-associative operators, I think you can get rid of your none: Option[Int] and just use None (since you no longer need to “dispatch” on its type).
June 20th, 2008 at 12:46 pm
Hi Daniel,
I prefer the former definition for add. Actually, I prefer the less clumsy:
However, I didn’t want to take away from the example
Using a colon as a function name suffix only alters the associativity, not the fixity of the function — parentheses would still be required (in fact, I have a function called
<*>:and I could show this if you like).The type of
NoneisOption[Nothing]and the type inferencer requires a typeOption[Int]at that point because of the method used in inferencing (a forward inferencer). You’re more than welcome to try it and see. The code at hand can be found at http://projects.workingmouse.com/public/scalaz/branches/3.0/As a general rule, whenever you try to do anything powerful with Scala, you find the type inferencer starts to let you down quite quickly.
June 22nd, 2008 at 5:05 am
Boy, you Haskell veterans…can’t get you to do anything that isn’t cryptic!
I’m not sure I understand why the fixity of the operator is an issue. All of the operators in your example are infix; you’re not using anything unary or anything like that. If your operators were all right-associative, the resulting AST would be the same as it is now with left-associative operators and parentheses. (wouldn’t it?)