SORU
15 AĞUSTOS 2014, Cuma


Bir ADT veri kurucular ile ilişkilendirir tür kodlama ile ilgili sorunlar nelerdir? (Scala gibi.)

Scala, cebirsel veri türleri sealed bir düzey tip hiyerarşileri olarak kodlanır. Örnek:

-- Haskell
data Positioning a = Append
                   | AppendIf (a -> Bool)
                   | Explicit ([a] -> [a]) 
// Scala
sealed trait Positioning[A]
case object Append extends Positioning[Nothing]
case class AppendIf[A](condition: A => Boolean) extends Positioning[A]
case class Explicit[A](f: Seq[A] => Seq[A]) extends Positioning[A]

case classcase objects, Scala oluşturur bir sürü şey gibi equals, hashCode, unapply (kullanılan desen eşleştirme) vb. bize çok temel özellikleri ve özellikleri, geleneksel soyut veri yapıları.

Önemli bir farkı da olsa varScala, "kurucular" kendi türleri vardır . veri . Örneğin aşağıdaki iki (ilgili REPLs Kopyalanmış) karşılaştırın.

// Scala

scala> :t Append
Append.type

scala> :t AppendIf[Int](Function const true)
AppendIf[Int]

-- Haskell

haskell> :t Append
Append :: Positioning a

haskell> :t AppendIf (const True)
AppendIf (const True) :: Positioning a

Hep Scala değişimi avantajlı tarafı olarak kabul ediyorum.

Sonuçtatür bilgi kaybı yok. Örneğin AppendIf[Int] Positioning[Int] çalışmaları devam ediyor.

scala> val subtypeProof = implicitly[AppendIf[Int] <:< Positioning[Int]]
subtypeProof: <:<[AppendIf[Int],Positioning[Int]] = <function1>

Aslındadeğeri hakkında derleme zaman ek bir sabit olsun. (Bu bağımlı yazarak sınırlı bir versiyonu diyebilir miyiz?)

Bu iyi kullanmak koymak olabilir – veri yapıcı bir değer oluşturmak için kullanılan ne olduğunu öğrendikten Sonra, buna daha fazla tür güvenlik eklemek için akış dinlenme yoluyla yayılır olabilir. Örneğin, bu Scala kodlama kullanan Oyun JSON, sadece sen JsObject, herhangi bir keyfi JsValue 20 *ayıklamak için izin verir.

scala> import play.api.libs.json._
import play.api.libs.json._

scala> val obj = Json.obj("key" -> 3)
obj: play.api.libs.json.JsObject = {"key":3}

scala> obj.fields
res0: Seq[(String, play.api.libs.json.JsValue)] = ArrayBuffer((key,3))

scala> val arr = Json.arr(3, 4)
arr: play.api.libs.json.JsArray = [3,4]

scala> arr.fields
<console>:15: error: value fields is not a member of play.api.libs.json.JsArray
              arr.fields
                  ^

scala> val jsons = Set(obj, arr)
jsons: scala.collection.immutable.Set[Product with Serializable with play.api.libs.json.JsValue] = Set({"key":3}, [3,4])

Haskell muhtemelen 25 ** bulunurdu. JsArray vb çalışma zamanında başarısız olur. Bu sorun da bilinen kısmi kaydı set şeklinde tezahür eder.

Veri kurucular Scala tedavi yanlış olduğu görüşünü defalarca dile getirildi– Twitter, e-posta listeleri, IRC, vb. Ne yazık ki bir kaç tane this answer Scala için Travis Brown, ve Argonaut tamamen işlevsel bir JSON Kütüphanesi tarafından dışında bu herhangi bir bağlantıları yok.

Argonot consciously Haskell yaklaşım (privateıng sınıfları ve el ile veri kurucular sağlayarak). Haskell kodlama ile bahsettiğim sorun Argonaut ile bulunduğunu görebilirsiniz. (Option düşkünlük göstermek için kullanması dışında.)

scala> import argonaut._, Argonaut._
import argonaut._
import Argonaut._

scala> val obj = Json.obj("k" := 3)
obj: argonaut.Json = {"k":3}

scala> obj.obj.map(_.toList)
res6: Option[List[(argonaut.Json.JsonField, argonaut.Json)]] = Some(List((k,3)))

scala> val arr = Json.array(jNumber(3), jNumber(4))
arr: argonaut.Json = [3,4]

scala> arr.obj.map(_.toList)
res7: Option[List[(argonaut.Json.JsonField, argonaut.Json)]] = None

Bir süredir bu durulması olmuştur, ama yine de Scala'nın kodlama yanlış yapan nedir anlamıyorum. Emin zamanlarda tür kesmesi engellemektedir, ama bu yanlış kararı için yeterince güçlü bir neden gibi görünmüyor. Neyi kaçırıyorum?

CEVAP
15 AĞUSTOS 2014, Cuma


Benim en iyi bildiğim için, dava sınıfların Scala'nın deyimsel kodlama kötü olabilir iki sebebi vardır: tür kesmesi, türü ve özgüllüğü. Eski ikinci muhakeme artan kapsam meselesi ise sözdizimsel kolaylık olsun.

Kistlerinin alt tiplerinin belirlenmesindeki sorunu nispeten kolay göstermek için:

val x = Some(42)

x türü istedin herhalde değil Some[Int], çıkıyor. Diğer, daha sorunlu bölgelerde benzer sorunlar oluşturabilir:

sealed trait ADT
case class Case1(x: Int) extends ADT
case class Case2(x: String) extends ADT

val xs = List(Case1(42), Case1(12))

xs tipi List[Case1]. Bu temeldegarantiliistediğin şey için değil. Bu soruna geçici bir çözüm elde etmek için, List gibi kaplar türü parametre kovaryant gerekir. Ne yazık ki, kovaryans tanıttı bir bütün kova sorunlar, aslında düşüyor sağlamlığına belli yapıları (örneğin Scalaz tavizler üzerine Monad yazın ve birkaç monad transformers tarafından izin kovaryant kaplar rağmen, aslında bu sağlıksız bunu yapmak için).

Yani, bu şekilde kodlama soyut veri yapıları kodunuzu biraz viral bir etkiye sahiptir. ADT kendini kistlerinin alt tiplerinin belirlenmesindeki ile başa çıkmak için ihtiyacınız var, ama değil sadeceherhiç yazmak konteyner hesaba uygunsuz anlarda senin ADT literatürde iniş olman gerekiyor.

Senin soyut veri yapıları kamu davası sınıfları kullanarak kodlamak için ikinci nedeni türü alanı karmaşık ile kaçınmaktır "olmayan türleri". Belirli bir bakış açısı, ADT durumlarda gerçekten türleri: veri. Neden bu şekilde soyut veri yapıları yanlış değil!), eğer sonra ADT davaların her biri için birinci sınıf bir tip olması fikrini taşımak için gereken şeyler, set kod nedenle artar.

Örneğin, yukarıdan ADT Cebir düşünün. Eğer bu ADT kullanan kodu ile ilgili bir sebep istiyorsanız, sürekli "Evet, eğer bu tür Case1? ise" düşünmem lazım Sadece bir soru kimse gerçekten değilihtiyacı varsormak, Case1 veri olduğu için. Özellikle coproduct bir dava için bir etiket. Hepsi bu.

Şahsen, yukarıda hakkında çok fazla umurumda değil. , Kovaryans ile unsoundness sorunlar gerçek ama ben genellikle sadece benim kaplar ve kullanıcıların değişmeyen talimat yapmayı tercih yani "yalakalık ve türleri açıklama". Ve aptalca, ama demirbaş kıvrımları çok olan alternatif tercih ederim ve "küçük harf" veri kurucular. müsait

Bir joker, bir üçüncü potansiyel dezavantajı, bu tür bir tür özgüllüğü teşvik eder (ya da daha doğrusu, izin verir) bir daha "nesne yönelimli" tarzı yere olgu özel işlevleri üzerinde bireysel ADT türleri. Bu şekilde benzetmeler (büyük sınıflar vs alt polimorfizmi) karıştırma kötü bir tarifi olduğunu çok az soru var bence. Ancak, bu sonucun yazılı durumlarda suçu olup olmadığı açık bir soru.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Julian Smith

    Julian Smith

    31 EKİM 2006
  • TheDroidDemos

    TheDroidDemo

    15 ŞUBAT 2011
  • wwjoshdu

    wwjoshdu

    18 ŞUBAT 2011