(To jest uwaga w nawiasach. Najpierw przeczytaj i zrozum pozostałe odpowiedzi).
Granice kontekstu w rzeczywistości uogólniają granice widoku.
Tak więc, biorąc pod uwagę ten kod wyrażony za pomocą ograniczenia widoku:
scala> implicit def int2str(i: Int): String = i.toString
int2str: (i: Int)String
scala> def f1[T <% String](t: T) = 0
f1: [T](t: T)(implicit evidence$1: (T) => String)Int
Można to również wyrazić za pomocą Context Bound, za pomocą aliasu typu reprezentującego funkcje od typu F
do typu T
.
scala> trait To[T] { type From[F] = F => T }
defined trait To
scala> def f2[T : To[String]#From](t: T) = 0
f2: [T](t: T)(implicit evidence$1: (T) => java.lang.String)Int
scala> f2(1)
res1: Int = 0
Powiązany kontekst musi być używany z konstruktorem typu * => *
. Jednak konstruktor typu Function1
jest miły (*, *) => *
. Użycie aliasu typu częściowo powoduje zastosowanie drugiego parametru typu z typem String
, dając konstruktor typu poprawnego rodzaju do użycia jako powiązany z kontekstem.
Istnieje propozycja umożliwiająca bezpośrednie wyrażanie częściowo zastosowanych typów w Scali, bez użycia aliasu typu wewnątrz cechy. Możesz wtedy napisać:
def f3[T : [X](X => String)](t: T) = 0