I have been trying to understand the answers given to the question asked in this post.
The code below reproduces the solution proposed in the accepted answer.
object Finder {
def find[T <: Node](name: String)(implicit e: T DefaultsTo Node): T =
doFind(name).asInstanceOf[T]
}
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]
}
I would understand it if the implicit were defined as
(implicit e: DefaultsTo[T, Node])
But instead it is defined in something that looks like infix notation. I never knew that a type DefaultsTo[T, Node]
could be written as T DefaultsTo Node
. Is this what is going on?
But instead it is defined in something that looks like infix notation. I never knew that a type DefaultsTo[T,Node] could be written as "T DefaultsTo Node". Is this what is going on ?
Yes. The rule is very simple: the type must have precisely 2 parameters. It's primarily intended for types with symbolic names like <:<
, but as you can see it works for alphanumeric names as well.
Scala specification, 3.2.8 Infix Types:
InfixType ::= CompoundType {id [nl] CompoundType}
An infix type
T1 op T2
consists of an infix operatorop
which gets applied to two type operandsT1
andT2
. The type is equivalent to the type applicationop[T1,T2]
. The infix operatorop
may be an arbitrary identifier.All type infix operators have the same precedence; parentheses have to be used for grouping. The associativity of a type operator is determined as for term operators: type operators ending in a colon ‘:’ are right-associative; all other operators are left-associative.
In a sequence of consecutive type infix operations
t0 op t1 op2 … opn tn
, all operatorsop1,…,opn
must have the same associativity. If they are all left-associative, the sequence is interpreted as(…(t0 op1 t1) op2…) opn tn
, otherwise it is interpreted ast0 op1 (t1 op2 (…opn tn)…)
.