การใช้ข้อมูลประเภทพีชคณิตคืออะไร


16

ฉันกำลังอ่านเกี่ยวกับประเภทข้อมูลพีชคณิต (ขอบคุณ Richard Minerich ฉันพบคำอธิบายที่ยอดเยี่ยมเกี่ยวกับแนวคิดนี้) ในขณะที่ฉันคิดว่าฉันเข้าใจความคิดประเภทผลรวมและประเภทผลิตภัณฑ์ ฯลฯ สิ่งที่ฉันไม่เข้าใจค่อนข้างมากคือวิธีที่ Algebraic Data Types นั้นมีประโยชน์นอกเหนือจากการระบุการจับคู่รูปแบบ สิ่งอื่น ๆ ที่เราสามารถทำได้ด้วยการจับคู่รูปแบบที่นอกเหนือจาก ADT


แก้ไข: ฉันไม่ได้ถามว่านักพัฒนาสามารถทำอะไรกับ ADT ที่ไม่สามารถทำได้กับวัตถุ ฉันกำลังถามว่ามีการดำเนินงานอื่น ๆ ที่ ADT อนุญาตหรือไม่ ตัวอย่างเช่นเราสามารถให้เหตุผลเพิ่มเติมเกี่ยวกับประเภทที่เกี่ยวข้องหากใช้ ADT หรือไม่ ADT อำนวยความสะดวกในการวิเคราะห์ประเภทบางประเภทที่ไม่สามารถทำได้หรือไม่


2
คุณสามารถทำอะไรกับวัตถุยกเว้นวิธีการโทร

1
ADT หมายถึง "ประเภทข้อมูลนามธรรม" ไม่ใช่ประเภทข้อมูลเชิงพีชคณิต
Rein Henrichs

4
@Rein: มันสามารถอ้างถึงอย่างใดอย่างหนึ่งขึ้นอยู่กับบริบท
sepp2k

4
@ Rein: มันแน่นอน (ซึ่งฉันค่อนข้างน่าประหลาดใจที่จะซื่อสัตย์): อย่างไรก็ตามบทความวิกิพีเดียสำหรับ ADT แสดงทั้งประเภทข้อมูลนามธรรมและประเภทข้อมูลเกี่ยวกับพีชคณิตเป็นความหมายที่เป็นไปได้ และ ADT นั้นถูกใช้เป็นตัวย่อสำหรับชนิดข้อมูลเชิงพีชคณิตตัวอย่างเช่นรายชื่อผู้รับจดหมาย Haskell และช่องทาง IRC
sepp2k

1
@Rein ฉันรู้ - แค่เบื่อพิมพ์ "Algebraic Data Type" ซ้ำแล้วซ้ำอีกและฉันคิดว่าคนจะสามารถเข้าใจสิ่งที่ฉันหมายถึงบริบท
Onorio Catenacci

คำตอบ:


10

ประเภทข้อมูลเชิงพีชคณิตมีความแตกต่างในการที่พวกเขาสามารถสร้างจาก "สิ่ง" หลายประเภท ตัวอย่างเช่น Tree สามารถมีอะไรก็ได้ (ว่างเปล่า), Leaf หรือ Node

data Tree = Empty
          | Leaf Int
          | Node Tree Tree

เนื่องจากโหนดประกอบด้วยต้นไม้สองต้นชนิดข้อมูลเชิงพีชคณิตจึงสามารถเรียกซ้ำได้

การจับคู่รูปแบบช่วยให้สามารถแยกประเภทข้อมูลเกี่ยวกับพีชคณิตในลักษณะที่รักษาความปลอดภัยได้ พิจารณาการนำความลึกและ pseudocode ไปใช้ต่อไปนี้:

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

เปรียบเทียบกับ:

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)

นี่เป็นข้อเสียที่โปรแกรมเมอร์ต้องจำไว้ว่าให้เว้นว่างไว้ก่อน Leaf เพื่อให้ไม่สามารถเข้าถึง field1 บนทรีเปล่าได้ เช่นเดียวกันกรณีใบไม้จะต้องประกาศก่อนกรณีโหนดเพื่อให้ไม่สามารถเข้าถึง field2 บนใบไม้ได้ ดังนั้นความปลอดภัยของประเภทจึงไม่ได้รับการบำรุงรักษาโดยภาษา แต่จะกำหนดภาระการรับรู้เพิ่มเติมให้กับโปรแกรมเมอร์ โดยวิธีการที่ฉันคว้าตัวอย่างเหล่านี้โดยตรงจากหน้าวิกิพีเดีย

แน่นอนว่าการพิมพ์ด้วยเป็ดสามารถทำได้ดังนี้:

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

ดังนั้นประเภทข้อมูลเชิงพีชคณิตอาจไม่ดีกว่า OOP ที่เทียบเท่าอย่างเคร่งครัด แต่จะให้ความตึงเครียดที่แตกต่างกันในการสร้างซอฟต์แวร์


9

ฉันไม่แน่ใจนักคำอธิบายนั้นยอดเยี่ยมมาก

ประเภทข้อมูลเชิงพีชคณิตถูกใช้เพื่อสร้างโครงสร้างข้อมูลเช่นรายการและต้นไม้

ตัวอย่างเช่นการแยกวิเคราะห์ต้นไม้แสดงได้อย่างง่ายดายด้วยโครงสร้างข้อมูลเกี่ยวกับพีชคณิต

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>
                | ...

มันจะไม่ใช้เวลามากขึ้นในการเป็นตัวแทนของภาษา C

แต่จริงๆแล้วคุณสามารถทำทุกอย่างเกี่ยวกับประเภทข้อมูลพีชคณิต เสียงกระเพื่อมพิสูจน์ให้เห็นว่าคุณสามารถทำทุกอย่างด้วยคู่และ ADT เพียงแค่ให้วิธีที่ปลอดภัยมากขึ้นและพิมพ์วิธีการนี้

แน่นอนถ้าคุณถามว่า "คุณสามารถทำอะไรกับ ADT ได้บ้างคุณไม่สามารถทำอะไรกับวัตถุได้" คำตอบคือ "ไม่มีอะไร" เพียงบางครั้ง (ส่วนใหญ่) คุณจะพบว่าโซลูชั่นของ ADT นั้นมีความละเอียดน้อยกว่าอย่างมากในขณะที่ส่วนที่ยึดตามวัตถุนั้นมีความยืดหยุ่นมากกว่า ดังนั้นเพื่อวางไว้ในแผนผังการแยกที่แสดงด้วย ADT:

If(Call(Ident('likes_ADTs'),[Ident('you')]),
   Call(Ident('use_ADTs'),[Ident('you')]),
   Call(Ident('use_no_ADTs'),[Ident('you')]))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.