อินเตอร์เฟสของ Java และคลาสประเภทของ Haskell: ความแตกต่างและความคล้ายคลึงกัน?


112

ในขณะที่ฉันเรียนรู้ Haskell ฉันสังเกตเห็นประเภทของคลาสซึ่งน่าจะเป็นสิ่งประดิษฐ์ที่ยอดเยี่ยมที่มีต้นกำเนิดจาก Haskell

อย่างไรก็ตามในหน้า Wikipedia ในประเภทคลาส :

โปรแกรมเมอร์กำหนดคลาสประเภทโดยการระบุชุดของฟังก์ชันหรือชื่อคงที่พร้อมกับประเภทที่เกี่ยวข้องซึ่งต้องมีอยู่สำหรับทุกประเภทที่เป็นของคลาส

ซึ่งดูเหมือนจะค่อนข้างใกล้เคียงกับอินเทอร์เฟซของ Java สำหรับฉัน (อ้างถึงหน้าอินเทอร์เฟซ (Java) ของ Wikipedia ):

อินเทอร์เฟซในภาษาโปรแกรม Java เป็นประเภทนามธรรมที่ใช้เพื่อระบุส่วนต่อประสาน (ในความหมายทั่วไปของคำศัพท์) ที่คลาสต้องใช้

สองสิ่งนี้ดูค่อนข้างคล้ายกัน: คลาสประเภท จำกัด พฤติกรรมของประเภทในขณะที่อินเทอร์เฟซ จำกัด พฤติกรรมของคลาส

ฉันสงสัยว่าความแตกต่างและความคล้ายคลึงกันระหว่างประเภทคลาสใน Haskell และอินเทอร์เฟซใน Java คืออะไรหรืออาจแตกต่างกันโดยพื้นฐาน

แก้ไข:ผมสังเกตเห็นแม้ยอมรับ haskell.org ว่าพวกเขามีความคล้ายคลึงกัน ถ้าพวกมันคล้ายกันมาก (หรือพวกมัน?) แล้วทำไม type class ถึงได้รับการยกย่องเช่นนี้?

แก้ไขเพิ่มเติม:ว้าวคำตอบที่ยอดเยี่ยมมากมาย! ฉันเดาว่าฉันจะต้องปล่อยให้ชุมชนตัดสินใจว่าอันไหนดีที่สุด อย่างไรก็ตามในขณะที่อ่านคำตอบทั้งหมดของพวกเขาดูเหมือนจะเป็นเพียงแค่บอกว่า"มีหลายสิ่ง typeclass สามารถทำในขณะที่อินเตอร์เฟซที่ไม่สามารถหรือต้องรับมือกับข้อมูลทั่วไป" ฉันอดไม่ได้ที่จะสงสัยว่ามีอินเทอร์เฟซใดบ้างที่สามารถทำได้ในขณะที่แว่นตาพิมพ์ไม่สามารถทำได้ นอกจากนี้ฉันสังเกตเห็นว่า Wikipedia อ้างว่าคลาสพิมพ์ดีดถูกประดิษฐ์ขึ้นครั้งแรกในกระดาษปี 1989 * "ทำอย่างไรให้โพลีมอร์ฟิซึมเฉพาะกิจน้อยลง" ในขณะที่ Haskell ยังคงอยู่ในอู่ในขณะที่โครงการ Java เริ่มต้นในปี 2534 และเผยแพร่ครั้งแรกในปี 2538 ดังนั้นบางทีแทนที่จะเป็นประเภทคลาสที่คล้ายกับอินเทอร์เฟซ แต่ในทางกลับกันอินเทอร์เฟซนั้นได้รับอิทธิพลจากประเภทคลาสหรือไม่?มีเอกสาร / เอกสารสนับสนุนหรือหักล้างเรื่องนี้หรือไม่? ขอบคุณสำหรับคำตอบทั้งหมดพวกเขาทั้งหมดให้ความกระจ่างมาก!

ขอบคุณสำหรับข้อมูลทั้งหมด!


3
ไม่ไม่มีอินเทอร์เฟซใดที่สามารถทำคลาสประเภทนั้นไม่ได้ด้วยข้อแม้สำคัญที่อินเทอร์เฟซโดยทั่วไปจะปรากฏในภาษาที่มีคุณสมบัติในตัวที่ไม่พบใน Haskell เมื่อมีการเพิ่มคลาสประเภทลงใน Java พวกเขาจะสามารถใช้คุณสมบัติเหล่านั้นได้เช่นกัน
CA McCann

8
หากคุณมีคำถามหลายข้อคุณควรถามหลายคำถามอย่าพยายามยัดเยียดคำถามทั้งหมดให้เป็นคำถามเดียว อย่างไรก็ตามเพื่อตอบคำถามสุดท้ายของคุณ: อิทธิพลหลักของ Java คือ Objective-C ( ไม่ใช่ C ++ ตามที่รายงานมักเป็นเท็จ) ซึ่งอิทธิพลหลักในทางกลับกันคือ Smalltalk และ C อินเตอร์เฟสของ Java เป็นการปรับโปรโตคอลของ Objective-C ซึ่งเป็นอีกครั้ง การทำให้เป็นทางการของแนวคิดของโปรโตคอลใน OO ซึ่งจะขึ้นอยู่กับแนวคิดของโปรโตคอลในระบบเครือข่ายโดยเฉพาะ ARPANet ทั้งหมดนี้เกิดขึ้นก่อนกระดาษที่คุณอ้างถึง ...
Jörg W Mittag

1
... อิทธิพลของ Haskell ที่มีต่อ Java เกิดขึ้นมากในภายหลังและ จำกัด เฉพาะ Generics ซึ่งได้รับการออกแบบร่วมกันโดยหนึ่งในนักออกแบบของ Haskell, Phil Wadler
Jörg W Mittag

5
นี่คือบทความ Usenet โดยแพทริค Naughton, หนึ่งในนักออกแบบเดิมของ Java: Java ได้รับอิทธิพลอย่างมากจาก Objective-C และไม่ c น่าเสียดายที่การโพสต์ต้นฉบับเก่ามากจนไม่ปรากฏในที่เก็บถาวรของ Google ด้วยซ้ำ
Jörg W Mittag

8
มีอีกคำถามหนึ่งที่ปิดไปแล้วเนื่องจากซ้ำกับคำถามนี้ แต่มีคำตอบเชิงลึกมากกว่านั้น: stackoverflow.com/questions/8122109/…
Ben

คำตอบ:


50

ฉันจะบอกว่าอินเทอร์เฟซเป็นเหมือนคลาสประเภทSomeInterface tที่ค่าทั้งหมดมีประเภทt -> whatever(ที่whateverไม่มีt) เนื่องจากด้วยชนิดของความสัมพันธ์การสืบทอดใน Java และภาษาที่คล้ายคลึงกันวิธีการที่เรียกนั้นขึ้นอยู่กับประเภทของวัตถุที่เรียกใช้และไม่มีอะไรอื่น

นั่นหมายความว่ามันยากมากที่จะสร้างสิ่งต่างๆเช่นadd :: t -> t -> tอินเทอร์เฟซโดยที่มันเป็นความหลากหลายในพารามิเตอร์มากกว่าหนึ่งตัวเนื่องจากไม่มีวิธีใดที่อินเทอร์เฟซจะระบุว่าประเภทอาร์กิวเมนต์และประเภทการส่งคืนของวิธีการเป็นประเภทเดียวกันกับประเภทของ วัตถุที่เรียกใช้ (เช่นประเภท "ตัวเอง") ด้วย Generics มีครับวิธีที่จะปลอมนี้โดยการอินเตอร์เฟซที่มีพารามิเตอร์ทั่วไปที่คาดว่าจะเป็นชนิดเดียวกับวัตถุที่ตัวเองเช่นวิธีการComparable<T>ไม่ได้ที่คุณคาดว่าจะใช้Foo implements Comparable<Foo>เพื่อให้ชนิดของการมีประเภทcompareTo(T otherobject) t -> t -> Orderingแต่นั่นยังต้องให้โปรแกรมเมอร์ทำตามกฎนี้และยังทำให้ปวดหัวเมื่อผู้คนต้องการสร้างฟังก์ชันที่ใช้อินเทอร์เฟซนี้พวกเขาจะต้องมีพารามิเตอร์ประเภททั่วไปซ้ำ

นอกจากนี้คุณจะไม่มีสิ่งต่างๆเช่นempty :: tเพราะคุณไม่ได้เรียกใช้ฟังก์ชันที่นี่จึงไม่ใช่วิธีการ


1
ลักษณะ Scala (โดยทั่วไปคืออินเทอร์เฟซ) อนุญาต this.type เพื่อให้คุณสามารถส่งคืนหรือยอมรับพารามิเตอร์ของ "self type" Scala มีคุณลักษณะที่แยกจากกันโดยสิ้นเชิงที่เรียกว่า "ประเภทตนเอง" ซึ่งไม่มีส่วนเกี่ยวข้องกับสิ่งนี้ นี่ไม่ใช่ความแตกต่างทางความคิดเพียงแค่ความแตกต่างของการนำไปใช้
ดิน

45

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

ด้วยวิธีนี้ความแตกต่างที่น่าสังเกตบางประการ:

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

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


1
คุณจะขยายประเภทแว่นตาอย่างไร? แว่นตาพิมพ์สามารถขยายแว่นตาประเภทอื่น ๆ ได้เช่นเดียวกับการที่อินเทอร์เฟซสามารถขยายอินเทอร์เฟซได้อย่างไร
CMCDragonkai

10
การอัปเดตคำตอบนี้อาจคุ้มค่าเนื่องจากการใช้งานเริ่มต้นของ Java 8 ในอินเทอร์เฟซ
คืนสถานะ Monica

1
@CMCDragonkai ใช่ตัวอย่างเช่นคุณสามารถพูดว่า "class (Foo a) => Bar a where ... " เพื่อระบุว่าคลาสประเภท Bar ขยายคลาสประเภท Foo เช่นเดียวกับ Java Haskell มีมรดกมากมายที่นี่
คืนสถานะ Monica

ในกรณีนี้ประเภทคลาสไม่เหมือนกับโปรโตคอลใน Clojure แต่มีความปลอดภัยประเภท?
nawfal

24

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

class Foobar a where
    foo :: a -> a -> Bool
    bar :: String -> a

สิ่งนี้หมายความว่าเมื่อคุณใช้ใช้ฟังก์ชันfooกับอาร์กิวเมนต์บางประเภทที่เป็นของคลาสFoobarมันจะค้นหาการนำไปใช้งานfooเฉพาะกับประเภทนั้นและใช้สิ่งนั้น สิ่งนี้คล้ายกับสถานการณ์ที่ตัวดำเนินการทำงานมากเกินไปในภาษาเช่น C ++ / C # ยกเว้นมีความยืดหยุ่นและเป็นแบบทั่วไป

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

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

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


ฉันกำลังดิ้นรนกับการทำความเข้าใจลำดับชั้นประเภทใน Haskell คุณคิดอย่างไรกับระบบประเภทต่างๆเช่น Omega? พวกเขาสามารถจำลองลำดับชั้นประเภทได้หรือไม่?
CMCDragonkai

@CMCDragonkai: ฉันไม่คุ้นเคยกับ Omega มากพอที่จะพูดจริงๆขอโทษ
CA McCann

16

ฉันได้อ่านคำตอบข้างบนแล้ว ฉันรู้สึกว่าฉันสามารถตอบได้ชัดเจนขึ้นเล็กน้อย:

"คลาสประเภท" ของ Haskell และอินเทอร์เฟซ Java / C # หรือ "ลักษณะ" ของ Scala นั้นคล้ายคลึงกันโดยทั่วไป ไม่มีความแตกต่างทางแนวคิดระหว่างพวกเขา แต่มีความแตกต่างในการนำไปใช้:

  • คลาสประเภท Haskell ถูกนำไปใช้กับ "อินสแตนซ์" ที่แยกจากข้อกำหนดประเภทข้อมูล ใน C # / Java / Scala ต้องใช้อินเทอร์เฟซ / ลักษณะเฉพาะในนิยามคลาส
  • คลาสประเภท Haskell อนุญาตให้คุณส่งคืนประเภทนี้หรือประเภทตนเอง ลักษณะ Scala ก็ทำได้เช่นกัน (this.type) โปรดทราบว่า "ประเภทตนเอง" ใน Scala เป็นคุณลักษณะที่ไม่เกี่ยวข้องกันโดยสิ้นเชิง Java / C # ต้องการวิธีแก้ปัญหาที่ยุ่งเหยิงด้วย generics เพื่อประมาณพฤติกรรมนี้
  • คลาสประเภท Haskell ให้คุณกำหนดฟังก์ชัน (รวมถึงค่าคงที่) โดยไม่ต้องป้อนพารามิเตอร์ประเภท "นี้" อินเตอร์เฟส Java / C # และลักษณะ Scala ต้องการพารามิเตอร์อินพุต "this" ในทุกฟังก์ชัน
  • คลาสประเภท Haskell ให้คุณกำหนดการใช้งานเริ่มต้นสำหรับฟังก์ชัน ลักษณะ Scala และอินเทอร์เฟซ Java 8+ C # สามารถประมาณค่าประมาณนี้ด้วยวิธีการขยาย

2
เพื่อเพิ่มวรรณกรรมบางส่วนในคำตอบนี้ฉันอ่านOn (Haskell) Type Classes และ (C #) Interfacesในวันนี้ซึ่งเปรียบเทียบกับอินเทอร์เฟซ C # แทน Javas แต่ควรให้ความเข้าใจในด้านแนวความคิดที่แยกความคิดของ อินเทอร์เฟซข้ามพรมแดนภาษา
daniel.kahlenberg

ฉันคิดว่าการประมาณบางอย่างสำหรับสิ่งต่างๆเช่นการใช้งานเริ่มต้นทำได้ค่อนข้างมีประสิทธิภาพมากกว่าใน C # ด้วยคลาสนามธรรมบางที?
Arwin

12

ในความคิดหลักของการเขียนโปรแกรมมีการสัมภาษณ์เกี่ยวกับ Haskell กับ Phil Wadler ผู้ประดิษฐ์คลาสประเภทซึ่งอธิบายความคล้ายคลึงกันระหว่างอินเทอร์เฟซใน Java และคลาสประเภทใน Haskell:

วิธีการของ Java เช่น:

   public static <T extends Comparable<T>> T min (T x, T y) 
   {
      if (x.compare(y) < 0)
            return x; 
      else
            return y; 
   }

คล้ายกับวิธี Haskell มาก:

   min :: Ord a => a -> a -> a
   min x y  = if x < y then x else y

ดังนั้นคลาสประเภทจึงเกี่ยวข้องกับอินเทอร์เฟซ แต่การติดต่อกันจริงจะเป็นวิธีการแบบคงที่พารามิเตอร์ด้วยประเภทดังกล่าวข้างต้น


นี่น่าจะเป็นคำตอบเพราะตามหน้าแรกของPhil Wadlerเขาเป็นผู้ออกแบบหลักการของ Haskell ในขณะเดียวกันเขาก็ออกแบบส่วนขยาย Generics สำหรับ Java ซึ่งรวมอยู่ในภาษาในภายหลังด้วย
Wong Jia Hau

10

นาฬิกาฟิลลิป Wadler พูดคุยศรัทธาวิวัฒนาการและการเขียนโปรแกรมภาษา Wadler ทำงานใน Haskell และเป็นผู้สนับสนุนหลักของ Java Generics


1
สิ่งที่เกี่ยวข้องอยู่ที่ประมาณ 25 เมตร (แม้ว่าการเริ่มต้นจะค่อนข้างตลก)
Fred Foo

8

อ่านSoftware Extension and Integration with Type Classesซึ่งมีตัวอย่างว่าคลาสประเภทสามารถแก้ปัญหาต่างๆที่อินเทอร์เฟซไม่ได้อย่างไร

ตัวอย่างที่ระบุไว้ในกระดาษ ได้แก่ :

  • ปัญหาการแสดงออก
  • ปัญหาการรวมกรอบ
  • ปัญหาของการขยายอิสระ
  • การกดขี่ข่มเหงของการสลายตัวที่โดดเด่นการกระจัดกระจายและการพันกัน

3
ลิงค์ตายด้านบน ลองหนึ่งนี้แทน
Justin Leitgeb

1
ตอนนี้คนที่ตายแล้วด้วย ลองอันนี้
RichardW

7

ฉันไม่สามารถพูดกับระดับ "hype" ได้ถ้ามันดูดี แต่คลาสประเภทใช่มีหลายวิธีเหมือนกัน ความแตกต่างหนึ่งที่ผมสามารถคิดก็คือว่ามัน Haskell คุณสามารถให้พฤติกรรมบางส่วนของชั้นประเภทของการดำเนินงาน :

class  Eq a  where
  (==), (/=) :: a -> a -> Bool
  x /= y     = not (x == y)
  x == y     = not (x /= y)

ซึ่งแสดงให้เห็นว่ามีการดำเนินการสองอย่างคือเท่ากัน(==)และไม่เท่ากัน(/=)สำหรับสิ่งที่เป็นอินสแตนซ์ของEqคลาสประเภท แต่การดำเนินการที่ไม่เท่ากันถูกกำหนดในรูปของเท่ากับ (ดังนั้นคุณจะต้องระบุเพียงอย่างเดียว) และในทางกลับกัน

ดังนั้นใน Java ที่อาจไม่ใช่กฎหมายที่จะเป็นดังนี้:

interface Equal<T> {
    bool isEqual(T other) {
        return !isNotEqual(other); 
    }

    bool isNotEqual(T other) {
        return !isEqual(other); 
    }
}

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


6

มีความคล้ายคลึงกัน (อ่าน: มีการใช้งานที่คล้ายกัน) และอาจนำไปใช้ในทำนองเดียวกัน: ฟังก์ชัน polymorphic ใน Haskell ใช้เวลาอยู่ใต้ฝากระโปรง 'vtable' แสดงรายการฟังก์ชันที่เกี่ยวข้องกับประเภทคลาส

ตารางนี้มักจะอนุมานได้ในเวลาคอมไพล์ สิ่งนี้อาจเป็นจริงน้อยกว่าใน Java

แต่นี้เป็นตารางของฟังก์ชั่นไม่ได้วิธีการ วิธีการผูกมัดกับวัตถุ Haskell typeclasses ไม่ใช่

ดูพวกมันค่อนข้างเหมือนยาสามัญประจำตัวของ Java


3

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

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

ตัวอย่างเช่นread :: Read a => String -> a. ดังนั้นหากคุณมีข้อมูลประเภทอื่น ๆ เพียงพอเกี่ยวกับวิธีที่คุณจะใช้ผลลัพธ์ของ "อ่าน" คุณสามารถให้คอมไพเลอร์พิจารณาได้ว่าจะใช้พจนานุกรมใดสำหรับคุณ

นอกจากนี้คุณยังสามารถทำสิ่งที่ต้องการinstance (Read a) => Read [a] where...ซึ่งจะช่วยให้คุณกำหนดเช่นการอ่านสำหรับใด ๆรายการของสิ่งที่อ่านได้ ฉันไม่คิดว่าจะเป็นไปได้ใน Java

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


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