2015-05-20 13 views
5

Yol bağımlı türlerini deniyorum ve bunun için bir scalaz.Equal örneği yazmaya çalışırken bir sorunla karşılaşıyorum. Aşağıdaki yapıya sahiptir: İlk b1 "unequalable" yapmak istedimscalaz.Equide bağımlı türler için

class A { 
    class B 
} 

val a1 = new A 
val b1 = new a1.B // type a1.B 

val a2 = new A 
val b2 = new a2.B //type a2.B 

(olduğuna dair bir haber var mı?) b2 derleme zamanında, şu elde:

import scalaz._ 
import Scalaz._ 

implicit def BEqual[X <: A#B]: scalaz.Equal[X] = Equal.equalA 

b1 === b1 //true 
b1 === b2 // doesn't compile, good 
b2 === b1 // doesn't compile, good 

Benim

implicit val BEqual: scalaz.Equal[A#B] = Equal.equalA 
: ikinci deney ile birbirine ancak diğer türleriyle karşılaştırıldığında edilecek A#B örneklerini sağlayan eşitlik az kısıtlayıcı yapmaya oldu 10

Ama beklendiği gibi çalışmaz: Ancak bu işler

b1 === b2 //doesnt' compile, === is not a member of a1.B 

: Yani

BEqual.equal(b1,b2) //compiles 
BEqual.equal(b1,"string") //doesnt' compile, good 

, ben === çalışmıyor neden bilmek istiyorum ve bir örneğini yazabilirsiniz eğer Equal'un tamamı A#B s için geçerli midir?

Ev içi demleme çözümünü örtülü dönüştürme ile denedim ve çalıştı.

implicit class abEqual(ab: A#B) { 
    def eqab(ab2: A#B) = ab == ab2 
} 

b1.eqab(b2) //ok 
b2.eqab(b1) //ok 
b1.eqab("String") //doesn't compile, good 

Peki bu neden scalaz.Equal ile çalışmıyor? BEqual İlk olarak

cevap

4

Eğer A#B herhangi alt tipi için bu alt tipi için bir Equal örneği sağlamak istiyoruz söylüyorsun. Derleyici b1 === görürse, b1 statik türü a.B olduğundan Equal[a.B] örneğini bulur. Bu, beklediğiniz gibi işler yapar.

İkinci BEqual numaralı telefon numaranızda, Equal örneğini yalnızca A#B için tanımlarsınız. Bubile derlenmeyeceği anlamına gelir, çünkü b1 statik türü A#B'dan daha özgün ve Equal tür parametresinde değişmezdir. Eğer değerler upcast Eğer örnek iyi çalışacaktır:

scala> val ab1: A#B = b1 
ab1: A#B = [email protected] 

scala> val ab2: A#B = b2 
ab2: A#B = [email protected] 

scala> ab1 === ab2 
res1: Boolean = false 

doğrudan BEqual.equal çağrı sürümünde, esasen aynı şey-yöntem argümanlar hep bildirdiğinden vardır gerçekleştirerek, bu nedenle bir şey geçirdiğinizde statik olarak yazılan ediyoruz a.B olarak bir A#B argümanı olarak, her şey iyi çalışır. El yapımı örtülü sınıfınızda, benzer şekilde sadece eski bir A#B ile çalışmak istediğinizi söylüyorsunuz.

Some(1) === Some(1) vs Option(1) === Option(1) (veya some(1) === some(1)) yazarken aynı türden şeyleri görebilirsiniz. Scalaz, Option[A: Equal] için Equal sağlar, ancak Some[A: Equal] için değildir ve ilk bağımsız değişken daha özel bir statik türe sahip olduğunda Option örneği bulunmaz.

Bu, Scalaz'ın Equal değişiminin kasıtlı olduğundan, etrafta çalışmak istediğiniz bir şey değildir. Bu bağlamda A#B değerleri ile A#B değerleri ile çalışmak istiyorsanız, bunları açıkça yayınlamanız gerekir.

+1

"ve" Equal ", tür parametresinde değişkendir". İşte orada, gözden kaçırdığım detay buydu! Katılıyorum 'etrafta çalışmak istemiyorum, doğru davranış! Teşekkürler! – Chirlo