# Terser syntax for first-class functions needing a context bound

I have the following function that looks up a mathematical operation that can be applied to a Numeric sequence based on a String

def getAction[T : Fractional]( op : String ) : Seq[T] => String =
op match {
case "add" => seq => seq.sum.toString
case "product" => seq => seq.product.toString
case "mean" => seq => {
implicit def intToFractional(i : Int) =
implicitly[Fractional[T]].fromInt(i);
(seq.sum / seq.length).toString
}
case "sqrt" => seq => seq.map(i => math.sqrt(i.toDouble)).toString
}


That works fine, except I would prefer to specify the type when applying the returned function rather than at the time or retrieval.

i.e. I want

getAction("sqrt")[Double](Seq(4.0))


rather than

getAction[Double]("sqrt")(Seq(4.0))


The only way I have found to do this is by defining a new class/trait with a generic context-bound apply.

abstract class Action {
def apply[T : Fractional](seq : Seq[T]) : String
}


Edit: Replaced with whole class rather than just the method because compilable solution was wanted.

object Main extends App {
import scala.math.Fractional
import Fractional.Implicits._
import scala.language.implicitConversions

abstract class Action {
def apply[T : Fractional](seq : Seq[T]) : String
}

def getAction( op : String ) : Action =
op match {
new Action {
def apply[T : Fractional](seq : Seq[T]) = seq.sum.toString
}
case "product" =>
new Action {
def apply[T : Fractional](seq : Seq[T]) = seq.product.toString
}
case "mean" =>
new Action {
def apply[T : Fractional](seq : Seq[T])= {
implicit def intToFractional(i : Int) =
implicitly[Fractional[T]].fromInt(i);

(seq.sum / seq.length).toString
}
}
case "sqrt" =>
new Action {
def apply[T : Fractional](seq : Seq[T]) =
seq.map(i => math.sqrt(i.toDouble)).toString
}
}

def getAction_v1[T : Fractional]( op : String ) : Seq[T] => String =
op match {
case "add" => seq => seq.sum.toString
case "product" => seq => seq.product.toString
case "mean" => seq => {
implicit def intToFractional(i : Int) =
implicitly[Fractional[T]].fromInt(i);
(seq.sum / seq.length).toString
}
case "sqrt" => seq => seq.map(i => math.sqrt(i.toDouble)).toString
}
}


However, this seems messy to be because of all the repeated anonymous class definitions and repeated type signatures. This makes the actual math operations less obvious than the first version.

Is there a better way?

Edit: here is a simple test suite that shows execution of both versions import org.scalatest.FunSuite

import org.scalatest.FunSuite

class Tests extends FunSuite {

test("v1"){
val act = Main.getAction_v1[Double]("sqrt")
assert(act(Seq(4.0)) === "List(2.0)")
}

test("v2") {
val act = Main.getAction("sqrt")
assert(act[Double](Seq(4.0)) === "List(2.0)")
}
}

-
your code won't even compile as given... –  Kim Jan 5 '13 at 16:26
@Kim I have provided a more complete sample for the the second version. Maybe the imports will make a difference for you? It compliles fine for me on 2.10.0-RC5. Thanks! –  vossad01 Jan 5 '13 at 16:54
getAction[Double]("sqrt")(Seq(4.0)) still doesn't compile. However, getAction[Double]("sqrt").apply(Seq(4.0)) does. –  Kim Jan 5 '13 at 17:03
@Kim Huh, that its unexpected, inlining the result of getAction (see the TestSuite I added) is not safe. I guess now I need to research why that does not work. I my guess is that it wants to use Seq(4.0) as the implicit parameter. Thanks for pointing that out! I am just learning scala. –  vossad01 Jan 5 '13 at 17:18
Yes, that is indeed the reason. –  Kim Jan 5 '13 at 20:55

How about not having to specify the type at all?

implicit class SeqWithAction[T:Fractional](seq:Seq[T]) {
def getAction( op : String ) : String =
op match {
case "product" => seq.product.toString
case "mean" => {
implicit def intToFractional(i : Int) =
implicitly[Fractional[T]].fromInt(i);
(seq.sum / seq.length).toString
}
case "sqrt" => seq.map(i => math.sqrt(i.toDouble)).toString
}
}
}
Seq(4.0).getAction("sqrt")

-
I like the result with respect to reductin code. Would this be considered good form in Scala? I am coming from mainly a C# background, and there this would likely be considered an abuse of extention methods. –  vossad01 Jan 5 '13 at 17:20
I think this is quite common in Scala. It's okay as long as you put your implicits into a separate object so the user of your library can choose whether to import them or not. –  Kim Jan 5 '13 at 20:53
You find this kind of thing a lot in DSLs, e.g. for testing. –  Kim Jan 5 '13 at 20:54