Cebirsel Veri Türlerinin Kullanım Alanları Nelerdir?


16

Cebirsel Veri Türleri hakkında okuyorum (Richard Minerich sayesinde kavramın bu mükemmel açıklamasını buldum ). Toplam türleri ve ürün türleri vb. ADT'nin kalıp eşleşmesinin ötesinde başka neler yapılabilir?


DÜZENLEME: Bir geliştiricinin nesnelerle yapılamayan ADT'lerle neler yapabileceğini sormuyorum. ADT'nin izin verdiği başka işlemler olup olmadığını soruyorum; örneğin, ADT'ler kullanılırsa ilgili türler hakkında ek akıl yürütmeler yapılabilir mi? ADT'ler onlarsız mümkün olmayan bir tür tip analizini kolaylaştırır mı?


2
Arama yöntemleri dışındaki nesnelerle ne yapabilirsiniz?

1
ADT aslında cebirsel veri türlerini değil, "soyut veri türünü" ifade eder .
Rein Henrichs

4
@Rein: Bağlama bağlı olarak ya atıfta bulunabilir.
sepp2k

4
@Rein: Gerçekten (dürüst olmak gerekirse oldukça şaşırtıcı buluyorum): Ancak ADT için wikipedia makalesi hem Özet Veri Türü hem de Cebirsel Veri Türü'nü olası anlamlar olarak listeliyor. ADT, örneğin Haskell posta listesi ve IRC kanalı üzerindeki cebirsel veri türleri için kısaltma olarak kullanılır.
sepp2k

1
@Rein, biliyorum - tekrar tekrar "Cebirsel Veri Türü" yazmaktan bıktım ve insanların bağlamda neyi kastettiğimi anlayabileceklerini düşündüm.
Onorio Catenacci

Yanıtlar:


10

Cebirsel Veri Türleri, çeşitli "şeylerden" oluşturulabilmeleri bakımından farklıdır. Örneğin, bir Ağaç hiçbir şey (Boş), Yaprak veya Düğüm içeremez.

data Tree = Empty
          | Leaf Int
          | Node Tree Tree

Bir Düğüm iki Ağaçtan oluştuğundan, cebirsel veri türleri özyinelemeli olabilir.

Örüntü eşleme, cebirsel veri türlerinin tür güvenliğini koruyacak şekilde yapısökülmesine olanak tanır . Aşağıdaki derinlik uygulamasını ve sözde kod eşdeğerini göz önünde bulundurun:

depth :: Tree -> Int
depth Empty = 0
depth (Leaf n) = 1
depth (Node l r) = 1 + max (depth l) (depth r)

nazaran:

switch on (data.constructor)
  case Empty:
    return 0
  case Leaf:
    return 1
  case Node:
    let l = data.field1
    let r = data.field2
    return 1 + max (depth l) (depth r)

Bunun dezavantajı, programcının Boş bir ağaçta alan1'e erişilmemesi için Yapraktan önce Boş yazması gerektiğini hatırlaması gerekir. Benzer şekilde, Leaf durumunun Leaf2'de field2 öğesine erişilmemesi için Node durumundan önce bildirilmesi gerekir. Böylece tip güvenliği bu nedenle dil tarafından korunmaz, aksine programcıya ek bilişsel yük getirir. Bu arada, bu örnekleri doğrudan wikipedia sayfalarından alıyorum.

Tabii ki, ördek yazarak bir dil şu şekilde yapabilir:

class Empty
  def depth
    0
  end
end

class Leaf
  def depth
    1
  end
end

class Node
  attr_accessor :field1, :field2

  def depth
    1 + [field1.depth, field2.depth].max
  end
end

Bu nedenle cebirsel veri türleri OOP eşdeğerlerinden kesinlikle daha iyi olmayabilir, ancak yazılım oluştururken çalışmak için farklı bir gerilim seti sağlarlar.


9

Ben açıklama tüm bu mükemmel olduğundan emin değilim .

Cebirsel Veri Türleri, listeler ve ağaçlar gibi veri yapıları oluşturmak için kullanılır.

Örneğin, ayrışan ağaçlar cebirsel veri yapıları ile kolayca temsil edilir.

data BinOperator = Add
                 | Subtr
                 | Div
                 | Mult
                 | Mod
                 | Eq
                 | NotEq
                 | GreaterThan
                 | LogicAnd
                 | LogicOr
                 | BitAnd
                 | BitOr
                 | ...

data UnOperator = Negate
                | Not
                | Increment
                | Decrement
                | Complement
                | Ref
                | DeRef


data Expression = Empty
                | IntConst Int
                | FloatConst Float
                | StringConst String
                | Ident String
                | BinOp BinOperator Expression Expression
                | UnOp UnOperator Expression Bool //prefix or not
                | If Expression Expression Expression
                | While Expression Expression Bool //while vs. do while
                | Block List<Expression>
                | Call Expression List<Expression>
                | ...

Aslında C dilini temsil etmek çok fazla zaman almazdı.

Ama gerçekten, her şeyi cebirsel veri türleriyle yapabilirsiniz. Lisp, her şeyi çiftlerle yapabileceğinizi kanıtlıyor ve ADT'ler bu yaklaşıma daha ayrıntılı ve güvenli bir yol sağlıyor.

Tabii ki, "ADT'lerle ne yapabilirsiniz, nesnelerle yapamayacağınız?" Diye sorarsanız, cevap "hiçbir şey" dir. Sadece bazen (çoğunlukla) ADT'lerin çözümlerini önemli ölçüde daha az ayrıntılı bulurken, nesnelere dayanan çözümler tartışmaya göre daha esnektir. ADT'lerle temsil edilen bir ayrıştırma ağacına koymak için:

If(Call(Ident('likes_ADTs'),[Ident('you')]),
   Call(Ident('use_ADTs'),[Ident('you')]),
   Call(Ident('use_no_ADTs'),[Ident('you')]))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.