2012-07-11 26 views
5

A => B ile List[A] => List[B] arasındaki işlevleri örtük olarak dönüştürmek istiyorum. Ben açık zamanla işlevini açıklama, bunuScalada örtülü kaldırma

val plusOne: (List[Int]) => List[Int] = (x: Int) => (x + 1) 

: Aşağıdaki kodu yazarken yazık ki, örtük uygulanmaz

implicit def lift[A, B](f: A => B): List[A] => List[B] = ... 

:

Aşağıdaki örtük tanım yazdı iyi çalışıyor.

Neden? Bunu nasıl düzeltebilirim?

UPDATE. Sorun, anonim işlevlere özgü gibi görünüyor. Karşılaştırma:

@Test 
def localLiftingGenerics { 
    implicit def anyPairToList[X, Y](x: (X, Y)): List[X] => List[Y] = throw new UnsupportedOperationException 

    val v: List[String] => List[Int] = ("abc", 239) 
} 

@Test 
def localLiftingFuns { 
    implicit def fun2ListFun[X, Y](f: X => Y): List[X] => List[Y] = throw new UnsupportedOperationException 

    val v: List[String] => List[Int] = ((x: String) => x.length) 
} 

İlki iyi bir şekilde derlenmiştir. İkincisi ise hata olarak işaretlenmiş

+0

"Implicit def" uygulamak için kullandığınız kodu sağlayabilir misiniz? –

+1

@ChrisJamesC Bir test vakası ile güncellendi –

+2

Bunu yapmak/yapmak istediğinize emin misiniz? "map" birkaç karakter için çok fazla netlik sağlar ve örn. val plusOne: (Liste [Int]) => Liste [Int] = _ map (_ + 1) 'aslında sürümünüzden daha kısa. –

cevap

6

:

anonim fonksiyonunun beklenen tip formunun ise scala.Fonksiyon N [ S , ve hellip ;, S n R] e beklenen tip R ... Böylece

, sonucu türüdür Eğer fonksiyon değeri görevden işlevi tanımı ayırmak sürece fonksiyonu (beklenen türde kurtulmak için) List[Int] olarak anlaşılmaktadır edilecektir:

val function = (x: Int) => (x + 1) 
val plusOne: (List[Int]) => List[Int] = function 

veya işlev türünü açıkça belirtin:

val plusOne: (List[Int]) => List[Int] = ((x: Int) => (x + 1)): Int => Int 
1

(Scala 2.9.1-1 (Java HotSpot (TM) 64-bit sunucu VM, Java 1.7.0_05)

Birinci gözlem: Çoğaltmak olursa fun2ListFun ve fun2ListFun elde edersiniz, örneğin `` bunu adlandırmak

found : String => <error> 
required: List[String] => List[Int] 

Note that implicit conversions are not applicable because they are ambiguous: 
both method fun2ListFun2 of type [X, Y](f: X => Y)List[X] => List[Y] 
and method fun2ListFun of type [X, Y](f: X => Y)List[X] => List[Y] 
are possible conversion functions from String => <error> to List[String] => List[Int] 
    val v: List[String] => List[Int] = ((x: String) => x.length) 

Bu derleyici geçerliyse hem implicits gördüğü gibi görünüyor.


İkinci gözlem:

Bölme

val v: List[String] => List[Int] = ((x: String) => x.length) /* Error*/ 

val f = ((x: String) => x.length) 
val v: List[String] => List[Int] = f /* Works */ 

içine derleyici mutlu ediyor.

1

Girdi değeri için örtülü dönüştürme derleniyor. Yani sadece anonim fonksiyonu

def localLiftingFuns { 
    implicit def fun2ListFun[X, Y](f: X => Y): List[X] => Y = throw new UnsupportedOperationException 

    val v: List[String] => Int = ((x: String) => x.length) 
} 

ikinci örtük dönüştürme kullanarak olası bir düzeltme çıkışı için bir sorun var:

def localLiftingFuns { 
    implicit def fun2ListFun[X, Y](f: X => List[Y]): List[X] => List[Y] = throw new UnsupportedOperationException 
    implicit def type2ListType[X](x:X): List[X] = throw new UnsupportedOperationException 

    val v: List[String] => List[Int] = ((x: String) => x.length) 
} 

Bu sürüm derler.

0

Derleyici, işlevin türü ile neler olup bittiğini anlamakta zorlanıyor. Ona biraz yardım olacaksa, işe yarar mıydı: The Scala Language Specification/İfadeler/Anonim Fonksiyonlar (6.23) 'a göre

scala> implicit def lift[A,B](f: A => B) = (_:List[A]).map(f) 
lift: [A, B](f: (A) => B)(List[A]) => List[B] 

scala> val f: List[Int] => List[Int] = ((_:Int) + 1):(Int => Int) 
f: (List[Int]) => List[Int] = <function1>