2013-03-07 20 views
15

Genel bilgi parametrelerine işlev hazırlayıcılarına izin vermek için bir sözdizimi var mı? Ben gibi bir yöntemde bunu sarabilirdiniz biliyorum:Scala'da, jenerik tip parametreleri * işlev * tanımlarıyla kullanılabilir mi?

def createLongStringFunction[T](): (T) => Boolean = { 
    (obj: T) => obj.toString.length > 7 
} 

ama sonra her tip T yöntemi çağırmak gerek ve yeni bir fonksiyon elde sonunda. Dil başvurusunu inceledim ve işlevinin sözdizimi sözdiziminin derleyici tarafından genel giriş türlerine sahip bir Functionn nesnesinin bir örneğine çevrildiğini görürsem, derleyici sihirbazının şu anda bu parametreleri gerçekleştirdiği anlaşılıyor. oluşturma. Aslında, "Functionn unbound'un tip parametrelerinden birini veya daha fazlasını bırakmamı sağlayan herhangi bir sözdizimi bulamadım." Tercih edeceğim şey şu satırlar boyunca bir şeydir:

Böyle bir şey var mı? Ya da, bu durumda, genişletilen yöntemin genel parametreleri olduğunda bir eta-genişletme işlevinin açık türü nedir?

Bu tamamen uyuşturulmuş ve yararsız bir örnektir. Tabi ki fonksiyonunu kullanabilirim.

cevap

18

Hayır, parametreler yalnızca işlevlere uygulanır ve işlev nesnesi değildir. Örneğin,

def f[T](x: T) = x  //> f: [T](x: T)T 
val g = f _   //> g: Nothing => Nothing = <function1> 
// g(2)    // error 
val h: Int=>Int = f _ //> h : Int => Int = <function2> 
h(2)     //> res0: Int = 2 

yöntem f polimorfik bir işlev nesnesinin g için dönüştürülemez. Gördüğünüz gibi, g'un türetilmiş türü aslında Function1[Nothing, Nothing]'dur, bu da işe yaramaz. Ancak, bir tür ipucu ile 'u Int argümanı için beklendiği gibi çalışabiliriz. ardından gibi tanımlanmıştır longStringFunction yana

+0

sayesinde Ben durumun olmasından korktum. Yöntemi genişletmek bu şekilde daha karmaşık durumlar için kapıyı açar. Ara metot olmadan bunu yapmanın bir yolunu bulamadığım halde, atamadaki tip ipucu şu şekilde şaşırtıcı bir şekilde taşıyabilir: ' def doStuff [T, U] (moreStuff: T => U) (obj: T) = dahaStuff (obj) val timeAndAHalf = doStuff [İnt, Çift] (_ * 1.5) _' 'def doStuff [T, U] değerinden oldukça fazla keser (moreStuff: T => U) (obj: T): U = dahaStuff (obj) val zamanıAndAHalf: Int => Çift = (num: Int) => doStuff [Int, Double] (sayı => sayı * 1.5) (sayı) ' – erich2k8

+4

Ne tip parametrelerinin işlev nesnelerine uygulanamaması nedenidir? –

1

bazı tip verilen olması gerekir değeri vardır.

val longStringFunction: (T) => Boolean = (obj: T) => obj.toString.length > 7 

Ancak, bir yöntem ile bir işlev nesnesini yeniden kullanabilirsiniz:

scala> val funObj: Any => Boolean = _.toString.size > 7 
funObj: Any => Boolean = <function1> 

scala> def typedFunction[T]: T => Boolean = funObj 
typedFunction: [T]=> T => Boolean 

scala> val f1 = typedFunction[String] 
f1: String => Boolean = <function1> 

scala> val f2 = typedFunction[Int] 
f2: Int => Boolean = <function1> 

scala> f1 eq f2 
res0: Boolean = true 

Bu işleri trait Function1[-T1, +R] tip T1 ait kontravaryant çünkü.

+0

Ah doğru. Bu etkili bir şekilde sadece daha kısıtlı bir türe dökülüyor. Aslında, yöntemi tamamen önleyebiliriz ve basitçe, örneğin, örn. 'val f1: String => Boolean = funObj' – erich2k8

7

Diyelim ki, sizin örnekte ihtiyacınız olan tek şey toString yöntemidir ve bu nedenle Any normal çözümdür. Bununla birlikte, bir tuple'daki her bir öğeye List gibi bir tür kurucu uygulamak gibi durumlarda daha üst düzey türleri kullanabilmek için çağrı vardır.

diğer cevaplar belirtildiği gibi, bunun için hiçbir doğrudan destek var, ama bunu kodlamak için oldukça güzel bir yol var: (yöntemler polimorfik iken)

scala olarak
trait ~>[A[_],B[_]] { 
    def apply[X](a : A[X]) : B[X] 
} 

type Id[A] = A //necessary hack 

object newList extends (Id ~> List) { 
    def apply[X](a : Id[X]) = List(a) 
} 

def tupleize[A,B, F[_]](f : Id ~> F, a : A, b : B) = (f(a), f(b)) 

tupleize(newList, 1, "Hello") // (List(1), List(Hello)) 
1

, Fonksiyon değerleri parametrik monomorfiktirler

Gölgesiz kitaplık, HLists ve daha birçok başka özellik üzerinde eşlenen polimorfik işlev değerlerini tanıtır.

aşağıdaki ref dikkate alınız: http://www.chuusai.com/2012/04/27/shapeless-polymorphic-function-values-1/ http://www.chuusai.com/2012/05/10/shapeless-polymorphic-function-values-2/

+0

Bu bağlantı soruyu yanıtlayabilirken, cevabın temel kısımlarını buraya dahil etmek ve referans için bağlantı sağlamak daha iyidir. Bağlantılı sayfa değiştiğinde yalnızca bağlantı yanıtları geçersiz olabilir. – Sasa

+0

@Sasam bu cevabın cevabın önemli kısmını içermesi! –

İlgili konular