paradigmatic
paradigmatic

Reputation: 40461

Default type for method calls

I would like to know how if it is possible to have a default type when calling a type-parameterized method in Scala. Suppose I have the following method somewhere:

def apply[A]( id: String )( implicit processor: Processor[A] ) =
  processor( data get id )

I would like A to be String, when the compiler has no hints about what type to infer. So I can overload my definition with:

def apply( id: String )( implicit processor: Processor[String] ) =
  processor( data get id )

But both methods will have the same signature after erasure... Is there any way to provide a default type ?

Upvotes: 4

Views: 188

Answers (2)

Aaron Novstrup
Aaron Novstrup

Reputation: 21017

You can achieve this by defining the following phantom type:

sealed class DefaultsTo[A, B]
trait LowPriorityDefaultsTo {
   implicit def overrideDefault[A,B] = new DefaultsTo[A,B]
}
object DefaultsTo extends LowPriorityDefaultsTo {
   implicit def default[B] = new DefaultsTo[B, B]
}

Then your method can be written

def apply[A]( id: String )( implicit e: A DefaultsTo String,
                                     processor: Processor[A] ) =
   processor( data get id )

The definition of overrideDefault guarantees that for any two specified types, A and B, the compiler can always supply an object of type DefaultsTo[A, B] (e.g. DefaultsTo[Int, String]). However, if one of the two types are unspecified (e.g. DefaultsTo[A, String]), the compiler will prefer to identify the two types (supplying, in the example, DefaultsTo[String, String], and thus inferring String for the unspecified type A).

As Naftoli Gugenheim pointed out in this mailing list thread, you can also achieve some nice syntax for use with context bounds:

class Has[B] {
   type AsDefault[A] = A DefaultsTo B
}

def apply[A : Has[String]#AsDefault : Processor](id: String) =
   implicitly[Processor[A]].apply(data get id)

Upvotes: 7

agilesteel
agilesteel

Reputation: 16859

In this case you can use a little trick

class C {
   def apply[A](id: String) = (processor: Processor[A]) => id + processor
   def apply(id: String)(implicit processor: Processor[String]) = id + processor
}

In a more general context, no idea sry...

EDIT

I forgot you need the processor to be implicit so it won't compile...

Upvotes: 0

Related Questions