ประเภทเป็นพลเมืองชั้นหนึ่ง


10

มาจากพื้นหลัง C ++ ฉันไม่เข้าใจว่าทำไมคนเราต้องการนิพจน์ประเภท / ประเภทในฐานะพลเมืองชั้นหนึ่ง? ภาษาเดียวที่ฉันรู้ว่ารองรับคุณสมบัตินี้คือ Aldor

มีใครบ้างที่มีวรรณกรรมเกี่ยวกับประเภทเป็นพลเมืองชั้นหนึ่งหรือรู้เหตุผลว่าทำไมจึงมีประโยชน์


3
ไอดริสก็มีสิ่งเหล่านี้เช่นกัน
ThreeFx

1
คุณถามเกี่ยวกับแนวคิดทั่วไปของ "type is value" (เรียกว่า "reflection" หรือ "metaclasses" ในภาษาต่างๆ) หรือเกี่ยวกับแนวคิดเฉพาะเพิ่มเติมของการแสดงออกประเภท
svick

1
@svick ฉันสนใจในภายหลัง น่าเสียดายที่ฉันไม่ได้พบเห็นอะไรทั่วๆไปเกี่ยวกับประเภทของนิพจน์ดังนั้นมันจะดีถ้าคุณสามารถแนะนำวรรณกรรมบางอย่างได้
paul98

คำตอบ:


11

ประเภท First class เปิดใช้งานสิ่งที่เรียกว่าการพิมพ์ตาม อนุญาตให้โปรแกรมเมอร์ใช้ค่าประเภทที่ระดับประเภท ตัวอย่างเช่นประเภทของคู่ทั้งหมดของจำนวนเต็มเป็นประเภทปกติในขณะที่คู่ของจำนวนเต็มทั้งหมดที่มีหมายเลขซ้ายขนาดเล็กกว่าหมายเลขที่ถูกต้องเป็นประเภทที่ขึ้นต่อกัน ตัวอย่างเบื้องต้นของมาตรฐานนี้คือรายการที่เข้ารหัสความยาว (โดยทั่วไปเรียกว่าVectorใน Haskell / Idris) โค้ดหลอกต่อไปนี้เป็นส่วนผสมของ Idris และ Haskell

-- a natural number
data Nat = Zero | Successor Nat

data Vector length typ where
  Empty : Vector Zero typ
  (::)   : typ -> Vector length typ -> Vector (Successor length) typ

รหัสชิ้นนี้บอกเราสองสิ่ง:

  • รายการว่างเปล่ามีความยาวเป็นศูนย์
  • consไอเอ็นจีองค์ประกอบลงในรายการสร้างรายการความยาว n + 1

มันดูคล้ายกับแนวคิดอื่นที่มี 0 และn + 1ใช่ไหม ฉันจะกลับมาที่

เราได้อะไรจากสิ่งนี้ ตอนนี้เราสามารถกำหนดคุณสมบัติเพิ่มเติมของฟังก์ชันที่เราใช้ ตัวอย่างเช่น: คุณสมบัติที่สำคัญappendคือความยาวของรายการผลลัพธ์คือผลรวมของความยาวของรายการอาร์กิวเมนต์สองรายการ:

plus : Nat -> Nat -> Nat
plus          Zero n = n
plus (Successor m) n = Successor (plus m n)

append : Vector n a -> Vector m a -> Vector (plus n m) a
append Empty  ys = ys
append (x::xs) ys = x :: append xs ys

แต่ทั้งหมดในทุกเทคนิคนี้ดูเหมือนจะไม่เป็นประโยชน์ในการเขียนโปรแกรมทุกวัน สิ่งนี้เกี่ยวข้องกับซ็อกเก็ตPOST/ GETคำขอและอื่น ๆ อย่างไร

ก็ไม่ได้ (อย่างน้อยก็ไม่มีความพยายามมาก) แต่มันสามารถช่วยเราในวิธีอื่นได้:

ประเภทที่พึ่งพาได้ช่วยให้เราสามารถกำหนดค่าคงที่ในโค้ด - กฎเป็นวิธีการทำงานของฟังก์ชัน เมื่อใช้สิ่งเหล่านี้เราจะได้รับความปลอดภัยเพิ่มเติมเกี่ยวกับพฤติกรรมของรหัสเช่นเดียวกับก่อนและหลังของไอเฟล สิ่งนี้มีประโยชน์อย่างมากสำหรับการพิสูจน์ทฤษฎีบทอัตโนมัติซึ่งเป็นหนึ่งในการใช้ที่เป็นไปได้สำหรับไอดริส

กลับมาที่ตัวอย่างข้างต้นความหมายของรายการความยาวเข้ารหัสคล้ายกับแนวคิดทางคณิตศาสตร์ของการเหนี่ยวนำ ในไอดริสคุณสามารถกำหนดแนวคิดของการเหนี่ยวนำในรายการดังต่อไปนี้:

              -- If you can supply the following:
list_induction : (Property : Vector len typ -> Type) -> -- a property to show
                  (Property Empty) -> -- the base case
                  ((w : a) -> (v : Vector n a) ->
                      Property v -> Property (w :: v)) -> -- the inductive step
                  (u : Vector m b) -> -- an arbitrary vector
                  Property u -- the property holds for all vectors

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

แน่นอนประเภทของการพึ่งพาเป็นเพียงการใช้ประเภทชั้นหนึ่ง แต่มันเป็นประเภทที่พบได้บ่อยที่สุดอย่างหนึ่ง การใช้งานเพิ่มเติมรวมถึงการคืนประเภทเฉพาะจากฟังก์ชั่นตามข้อโต้แย้ง

type_func : Vector n a -> Type
type_func Empty = Nat
type_func v     = Vector (Successor Zero) Nat

f : (v : Vector n a) -> type_func v
f Empty = 0
f vs    = length vs :: Empty

นี่เป็นตัวอย่างที่ไร้สาระ แต่มันแสดงให้เห็นถึงสิ่งที่คุณไม่สามารถเลียนแบบได้หากไม่มีประเภทชั้นหนึ่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.