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.

4 Responses to “Applicative Functors in Scala”

  1. Daniel Spiewak Says:

    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.

  2. Daniel Spiewak Says:

    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).

  3. Tony Morris Says:

    Hi Daniel,
    I prefer the former definition for add. Actually, I prefer the less clumsy:

    val add = curried((_: Int) + (_: Int) + (_: Int))
    

    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 &mdash; parentheses would still be required (in fact, I have a function called &lt;*&gt;: and I could show this if you like).

    The type of None is Option[Nothing] and the type inferencer requires a type Option[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.

  4. Daniel Spiewak Says:

    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?)

Leave a Reply