2016-03-18 14 views
1

Bunun işe yarayacağını hayal ettim. Açıkça yanlış bir şey yapıyorum? Lambda hesabı: Scala'ya uygula

val apply = (f: Any => Any, v: Any) => f(v) 
val square = (x: Int) => x * x 

başvururum hayal (kare, 10) 100

neden olacaktır Ama bir hata alıyorum: Burada

:15: error: type mismatch; 
found : Int => Int 
required: Any => Any 
     apply(square, 100) 

ne eksik?

cevap

3

İşlevler dönüş türlerinde eşdeğerdir, ancak argümanlarda kontravaryanttır. Int => Int, 'un bir alt sınıfıdır, ancak Any => Int veya Any => Any'un bir alt sınıfıdır (eğer öyleyse, örneğin String parametresinin girildiği bir bağlamda kullanabilirsiniz; Int).

cosider bu:

val foo: Function[Int, Int] = { x => x * x }  
def bar(f: Any => Any)(arg: Any): Any = f(arg) 

bar(foo)("foo") //??? 

Int => Int eğer Any => Any bir alt sınıfı olan, ardından son satırı geçerli olacaktır. Ancak, bu olamaz çünkü foo parametresinin String parametresiyle çağrılmasına neden olur.

Diğer taraftan, Any => Int'un bir alt notu Int => Int'dur (önceki herhangi bir yerde gerekli olan eskileri kullanabilirsiniz). "Kontravaryant" olmanın anlamı budur.

+0

Eklemeye değer: eğer 'apply' (soruda) tanımını değiştirirseniz, "T uygulanamazsınız" = (f: T => T, v: T) => f (v) ', iş, çünkü bu şekilde v, f'nin girişi ve f'nin çıktılarının aynı tip olduğu bilinir. –

+0

@TzachZohar "Aynı türde olduğu bilinen" oldukları için değil (orijinal örnekte olduğu gibi), daha çok [Uygula] 'yı uygula ve [geçerli] uygula [uygula] temelde iki farklı işlevdir bu durum. – Dima

+0

@Dima, eğer işlevler argümanlarında kontravaryant ise, Any => Int Int => Int? –