SORU
17 EKİM 2012, ÇARŞAMBA


Scala açıkça bağımlı türlerini desteklemiyor neden?

Orada yol bağımlı türleri ve bence mümkün express hemen hemen tüm özellikleri bu dilleri olarak kötülüğe doğru yöneldi ya da Agda bulunan Scala, ama merak ediyorum neden Scala desteklemiyor this daha açık bir şekilde olduğu gibi çok güzel diğer alanlar (Dolaylı olarak) ? Gibi birşey kaldı "gerekli değil" ?

CEVAP
17 EKİM 2012, ÇARŞAMBA


Kenara sözdizimsel kolaylık, tek tip, yol-bağımlı türleri ve örtülü değerlerin birleşimi Scala shapeless ispat etmeye çalıştım bağımlı olarak yazmak için şaşırtıcı derecede iyi bir destek var, demektir.

Bağımlı türleri için Scala içsel desteği path-dependent types). Bu bir tür seçici bir yol üzerinden bir nesne (örn. bağlı izin değer) grafik çok gibi

scala> class Foo { class Bar }
defined class Foo

scala> val foo1 = new Foo
foo1: Foo = Foo@24bc0658

scala> val foo2 = new Foo
foo2: Foo = Foo@6f7f757

scala> implicitly[foo1.Bar =:= foo1.Bar] // OK: equal types
res0: =:=[foo1.Bar,foo1.Bar] = <function1>

scala> implicitly[foo1.Bar =:= foo2.Bar] // Not OK: unequal types
<console>:11: error: Cannot prove that foo1.Bar =:= foo2.Bar.
              implicitly[foo1.Bar =:= foo2.Bar]

Kanımca, yukarıda yeterli olmalı cevap soru "Scala bir bağımlı olarak yazılan dil?" olumlu: çok açık o tür olan seçkin tarafından değerleri olan kendi önekleri.

Ancak, sık sık Scala değil itiraz bu bir "tamamen ön tanımlı olarak Agda ya Coq veya İdris bulunan dependent sum and product types yok, çünkü" bağımlı tür dil. Bu bir ölçüde temelleri, yine de deneyeceğim üzerinden form fiksasyon yansıtır ve Scala genellikle kabul edilmektedir daha çok bu diğer dillere daha yakın olduğunu gösteriyor bence.

Terminoloji rağmen, bağımlı toplamı türleri (ayrıca Sigma türleri olarak da bilinir), ikinci değer türünün ilk değerine bağlı olduğu değerler sadece bir çift vardır. Bu Scala, doğrudan gösterilebilir

scala> trait Sigma {
     |   val foo: Foo
     |   val bar: foo.Bar
     | }
defined trait Sigma

scala> val sigma = new Sigma {
     |   val foo = foo1
     |   val bar = new foo.Bar
     | }
sigma: java.lang.Object with Sigma{val bar: this.foo.Bar} = $anon$1@e3fabd8

ve aslında, bu 2.10 önce Scala encoding of dependent method types which is needed to escape from the 'Bakery of Doom' (veya-Ydependent-yöntem deneysel türleri Scala derleyici seçeneği ile daha önce) çok önemli bir parçasıdır.

Bağımlı ürün türleri (Pi türleri aka) aslında bir tür değerleri işlevleri vardır. Bağımlı programlama dilleri için yazılan statically sized vectors ve diğer poster çocukların temsili için anahtar. Scala Pi tür yol bağımlı türleri, tek tip ve kapalı parametreleri bir arada kullanarak kodlama yapabiliriz. İlk biz türü bir değer türü T U, bir işlevi temsil edecek olan bir özellik tanımlayın

scala> trait Pi[T] { type U }
defined trait Pi

Bu tür kullanır, daha polimorfik bir yöntem tanımlayabiliriz

scala> def depList[T](t: T)(implicit pi: Pi[T]): List[pi.U] = Nil
depList: [T](t: T)(implicit pi: Pi[T])List[pi.U]

(sonuç List[pi.U]) yazın yol-bağımlı tip pi.U kullanımına dikkat edin. T türü değeri göz önüne alındığında, bu fonksiyon türü, söz konusu T değerine karşılık gelen değerler(n) boş bir liste döndürür.

Şimdi tutmak istiyoruz işlevsel ilişkiler için uygun değerleri ve örtük tanık tanımlayın

scala> object Foo
defined module Foo

scala> object Bar
defined module Bar

scala> implicit val fooInt = new Pi[Foo.type] { type U = Int }
fooInt: java.lang.Object with Pi[Foo.type]{type U = Int} = $anon$1@60681a11

scala> implicit val barString = new Pi[Bar.type] { type U = String }
barString: java.lang.Object with Pi[Bar.type]{type U = String} = $anon$1@187602ae

Şimdi burada bizim Pi-tipi-kullanarak eylem, işlevidir

scala> depList(Foo)
res2: List[fooInt.U] = List()

scala> depList(Bar)
res3: List[barString.U] = List()

scala> implicitly[res2.type <:< List[Int]]
res4: <:<[res2.type,List[Int]] = <function1>

scala> implicitly[res2.type <:< List[String]]
<console>:19: error: Cannot prove that res2.type <:< List[String].
              implicitly[res2.type <:< List[String]]
                    ^

scala> implicitly[res3.type <:< List[String]]
res6: <:<[res3.type,List[String]] = <function1>

scala> implicitly[res3.type <:< List[Int]]
<console>:19: error: Cannot prove that res3.type <:< List[Int].
              implicitly[res3.type <:< List[Int]]

(not burada kullandığımız Scala <:< alt-tanık operatör yerine =:= res2.type res3.type tek tip ve dolayısıyla daha hassas daha türleri biz doğrulanıyor üzerinde OLUŞTURDUĞU).

Scala pratikte, ancak, Sigma ve Pi tür kodlama ve Agda ya da İdris biz gibi oradan işlem başlatmayız. Bunun yerine yol-bağımlı tip, tek tip kullanın ve doğrudan implicits. Bu şekilsiz dışarı nasıl oynadığını çok sayıda örnek bulabilirsiniz: , , , *, generic Zippers *scrap your boilerplatecomprehensive HListsextensible records24 vb. vb.

Görebildiğim tek kalan itiraz Pi türü yukarıdaki kodlama-bağlıymış ifade edilebilir değerler singleton türleri gerektirir. Ne yazık ki Scala bu referans olmayan türlerinden değerleri için referans türlerinden değerleri (esp. mümkün değildir örn. İnt). Bu bir utanç, ama bir iç zorluk: Scala türü denetleyicisi temsil ettiği tek tip olmayan referans değerler içten, ve orada oldu couple experiments yapma bunları doğrudan ifade edilebilir. Uygulamada fairly standard type-level encoding of the natural numbers ile bu sorunu çözebiliriz.

Her durumda, bu hafif bir etki alanı kısıtlama bağımlı yazılan bir dil olarak Scala durumu itiraz olarak kullanılabileceğini sanmıyorum. Eğer öyleyse, o aynı tuhaf bir sonuç olurdu Bağımlı ML tek doğal sayı değerleri bağımlılıkları verir) için de söylenebilir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Alexey - servant of Christ

    Alexey - ser

    15 EYLÜL 2007
  • Makeup Lover

    Makeup Lover

    12 HAZİRAN 2011
  • Sorikan

    Sorikan

    3 ŞUBAT 2008