2011-01-15 8 views
13

İşlev ve nesne arasında geçiş yapmak istediğimde scalaz|> operatörünü kullanabilirim, böylece daha fazla okunabilirlik elde edilebilir. Size bir model işlevi getirmeme izin verin: Şimdi, her iki şekilde de yazabilirim: anahtar işlevi ve nesnesi ile scalaz '|>

"aoeu" |> length2 
length2("aoeu")
Ancak bu işlevi daha genel olarak tanımlarsam, çalışmayı durdurur.
def length2(x:SeqLike[_,_]) = x.length * 2 
length2("aoeu") // ok 
"aoeu" |> length2 // doesn't work
Derleyici neden bunu anlayamıyor? String'dan, SeqLike özelliğindeki bazı sınıf karıştırmalarına kesinlikle örtük bir dönüşüm vardır.

+0

Zor. İlk başta düşündüm çünkü bir seferde sadece bir örtüye sahip olabilirsiniz ama şimdi bir yerde gizli bir varyans sorunu da var gibi görünmektedir… – Debilski

+2

@Debilski, scalaz'da nerede? | Kendi kimliğimi tanımlamaya çalıştım, bence “tek bir örtülü kural” onu uygulamamayı engelliyordu: “aoeu”, “|>” yöntemi ile sınıfa ve sonra tekrar “SeqLike” 'e dönüştürülmelidir. – huynhjl

+1

Hata mesajını göster. Herkesin Scalaz'ın hazır bulunmadığı, ancak hata mesajları genellikle neyin yanlış gittiğini açıklar. –

cevap

12
scala> "aoeu" |> length2 
<console>:14: error: type mismatch; 
found : (scala.collection.SeqLike[_, _]) => Int 
required: (java.lang.String) => ? 
     "aoeu" |> length2 

hata mesajı oldukça açık: Eğer artık şöyle beyan eğer çalışır mı. String den SeqLike[_,_] bir kapalı dönüştürme olmasına rağmen

, (SeqLike[_, _]) => Int den String => ? için bir dönüşüm vardır.

Bu

aşağıdaki örtülü dönüşümü kullanılarak tespit edilebilir:

implicit def liftFun[X, T <% X, U](f: (X) => U): (T) => U = { 
    def g(t:T) = f(t) 
    g _ 
} 

Düzen 2: burada olmayan bir scalaz operatördür.

class Pipe[T](t:T) { 
    def |%>[X, U](f: (X) => U)(implicit ev: T <%< X) = f(t) 
} 
implicit def toPipe[T](t:T) = new Pipe(t:T) 

Sonra bu gibi kullanabilirsiniz:

def l1(a:String) = a.length 
def l2(a:Seq[_]) = a.length * 2 

"abc" |%> l1 
"abc" |%> l2 

Bu örtük bir kanıtı olduğu sürece bir T üzerinde ancak X doğrudan çalışmayan bir fonksiyonu almaya |%> verir T'dan X'a dönüştürme.

2

Gerekirse varoluşsal türleri kullanmayın. İşleri kırıyorlar ve burada gerekli değiller. Diğer taraftan, diğer cevaptaki hatayı görmek işleri daha net bir hale getirdi. |>'u kullandığınızda iki tane örtülü dönüşüm var.

def length2[CC <% SeqLike[_, _]](x: CC) = x.length * 2 
+1

Bu döndürür: '(CC) => scala.collection.seqLike [_, _]' türünde kanıt parametresi için örtülü değer bulunamadı – huynhjl