ระบบประเภทของ Haskell เป็นอุปสรรคต่อการทำความเข้าใจการเขียนโปรแกรมที่ใช้งานได้จริงหรือไม่? [ปิด]


33

ฉันกำลังศึกษา Haskell เพื่อจุดประสงค์ในการทำความเข้าใจเกี่ยวกับการเขียนโปรแกรมฟังก์ชั่นด้วยความคาดหวังว่าฉันจะใช้ความเข้าใจที่ฉันได้รับในภาษาอื่น ๆ (Groovy, Python, JavaScript เป็นหลัก)

ฉันเลือกแฮสเค็ลล์เพราะฉันรู้สึกว่ามันใช้งานได้อย่างหมดจดและไม่ยอมพึ่งพารัฐ

ฉันไม่ได้เลือกที่จะเรียนรู้ Haskell เพราะฉันสนใจที่จะสำรวจระบบที่เข้มงวดมาก ๆ

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


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

4
@ ใช่แล้ว แต่รายชื่อของคุณจะต้องเหมือนกัน เชื่อใจฉันสิ่งนี้สามารถเข้าได้แม้จะมีการอนุมานแบบ
Eric Wilson

13
@FarmBoy และมีอะไรผิดปกติกับการใช้อาจจะ? Java ทำให้คุณใช้อาจจะในทุกชั้นเรียนซึ่งเป็นสิ่งที่แปลกที่จะทำ
ทางเลือก

3
และถ้าคุณจริงๆต้องการที่จะใช้รายการที่แตกต่างกันแน่นอนคุณสามารถใช้ชนิดข้อมูลเกี่ยวกับพีชคณิต
ทางเลือก

1
@ ช่างถา ณ ณ จุดนี้เราลืมคำถามเดิมของฉันไปแล้วซึ่งเป็นคำถามที่ถูกต้องสมบูรณ์
Eric Wilson

คำตอบ:


40

ฉันเชื่อว่าการทำความเข้าใจระบบประเภทของ Haskell เป็นเครื่องขยายเสียงเพื่อทำความเข้าใจกับการเขียนโปรแกรมการทำงาน

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

Haskell ป้องกันคุณจากการผลักสิ่งต่าง ๆ ใต้พรมบังคับให้คุณจัดการกับโครงสร้างของโปรแกรมของคุณอย่างชัดเจนและสอนภาษาให้คุณอธิบายโครงสร้างเหล่านี้: ภาษาประเภท การทำความเข้าใจกับประเภทต่างๆโดยเฉพาะประเภท Rich เช่นเดียวกับ Haskell จะทำให้คุณเป็นโปรแกรมเมอร์ที่ดีขึ้นในทุกภาษา

หาก Haskell ไม่ได้ถูกพิมพ์อย่างหนักแนวคิดเช่น monads ฟังก์ชั่นการใช้งานและสิ่งที่คล้ายกันจะไม่ถูกนำไปใช้กับการเขียนโปรแกรม


2
นี่คือคำตอบที่ดีการเพิ่มของฉันคือในขณะที่ระบบพิมพ์อาจดูแปลก ๆ ในตอนแรกในภายหลังเมื่อคุณเริ่มเรียนรู้แนวคิดขั้นสูงเพิ่มเติมคุณจะเห็นว่ามีบางสิ่งที่สามารถทำได้เนื่องจากการยึดติดกับประเภทนั้น ระบบ (เพิ่ม STM และ Data Parallel ในรายการด้านบน) สิ่งที่ไม่ใช่ตัวเริ่มในระบบประเภทอื่น ๆ นั้นเหมาะสมกับระบบ Haskell อย่างเป็นธรรมชาติ คำแนะนำของฉัน: ติดกับมันสักครู่ปล่อยให้มันจมในช่วงเวลา (มันไม่ใช่ภาษา "อัด")
anon

2
ฉันรู้ว่านี่เป็นคำตอบที่เก่ามาก แต่ฉันไม่เห็นด้วย ฉันคิดว่าอย่างชัดเจนเท่าที่บางสิ่งอาจเป็นภาษาระบบพิมพ์โดยเฉพาะอย่างยิ่งกับพระมหากษัตริย์เช่น State และ Parsec กวาดเศษตันของสิ่งต่าง ๆ ใต้พรม จริงๆแล้วนี่เป็นสิ่งที่รบกวนความสามารถของฉันในการเรียนรู้ห้องสมุดภาษา
Savanni D'Gerinel

4
@ SavanniD'Gerinel: ฉันคิดว่าในคำตอบนี้ "การผลักสิ่งใต้พรม" ไม่ได้หมายถึงการเพิ่มฟังก์ชันการทำงานโดยปริยาย (ซึ่ง Haskell ทำในวิธีการควบคุมเช่นผ่าน monads และช่วยลดสำเร็จรูป) แต่ค่อนข้างอนุญาตรหัสบางส่วน ทำสิ่งที่ไม่คาดหวังให้ทำ เช่น: ฟังก์ชันบริสุทธิ์ใน Haskell จะไม่มีผลข้างเคียง ระยะเวลา ในภาษาอื่น ๆ อีกมากมายที่คุณสามารถสัญญาได้ในเอกสารของฟังก์ชั่น แต่ไม่มีสิ่งใดในภาษาของคุณที่จะป้องกันคุณจากการผลักในผลข้างเคียงบางแห่งในรหัสของคุณ
Giorgio

33

ภาษาที่ใช้งานได้มากที่สุดคือ Scheme ที่กล่าวว่าระบบประเภท Haskell เป็นตัวบ่งชี้ความบริสุทธิ์ของมัน มันเป็นคำถามที่ว่า "วัดความบริสุทธิ์ได้อย่างไร" ระบบการพิมพ์ของ Haskell IOช่วยให้คุณได้อย่างง่ายดายวงล้อมปิดการกระทำที่ไม่บริสุทธิ์ใน ในการทำเช่นนั้นคุณต้องใช้ระบบประเภทคงที่

แต่สมมุติว่าระบบประเภทของ Haskell ไม่มีส่วนเกี่ยวข้องกับการตั้งโปรแกรมการทำงาน มันคงเป็นความสูงของความโอหังที่จะอ้างว่าระบบประเภทจะไม่ช่วยคุณในความพยายามทางการศึกษานี้ ระบบพิมพ์ของ Haskell นั้นสมบูรณ์และซับซ้อนและน่าสนใจกว่าเมื่อเปรียบเทียบกับระบบพิมพ์ของ C ++ และ OCaml

มันเป็นอุปสรรคหรือไม่? ไม่ฉันคิดว่ามันเป็นสินทรัพย์ ลองพิจารณาวิธีจัดการกับความขี้เกียจของ Haskell โดยไม่IOยกตัวอย่าง


8
ระบบประเภทของ +1 Haskell สามารถเป็นเพื่อนของคุณได้เมื่อคุณคุ้นเคยกับมัน
Larry Coleman

"ในการทำเช่นนั้นคุณต้องใช้ระบบชนิดคงที่" จริงๆ?
Jon Harrop

1
"น่าสนใจมากขึ้นเมื่อเปรียบเทียบกับระบบพิมพ์ของ C ++ และ OCaml" คุณเคยศึกษาโมดูลอันดับหนึ่งที่สูงขึ้นของ OCaml และพิมพ์ระบบวัตถุที่อนุมานและตัวแปรหลากหลายรูปแบบหรือไม่?
Jon Harrop

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

20

Clojure เป็นแบบไดนามิกและเกือบจะบริสุทธิ์เหมือน Haskell ดังนั้นจึงมีข้อโต้แย้งที่ดีว่าระบบประเภทของ Haskell นั้นเป็นตัวเลือกการออกแบบมากกว่าความต้องการแน่นอน ทั้งสองมีจุดแข็งของพวกเขาดังนั้นคุณอาจต้องการพิจารณา Clojure หากคุณไม่ชอบความแข็งแกร่งของ Haskell (แต่ดูด้านล่าง)

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


สิ่งที่ควรทราบอีกประการหนึ่ง: ฉันเรียนรู้การเขียนโปรแกรมการใช้งานโดยใช้ทั้ง Scheme และ Haskell ในเวลาเดียวกัน (สมัยก่อนเป็นคลาสและหลังเรียนสนุก) ฉันพบว่าความเข้าใจการเรียกซ้ำนั้นง่ายกว่ามากเมื่อใช้การจับคู่รูปแบบของ Haskell มากกว่ากับifs และconds ใน Scheme ซึ่งฉันจินตนาการว่าจะพาไปที่ Clojure ด้วย
Tikhon Jelvis

@ Larry Coleman: +1 สำหรับการอธิบายประสบการณ์ของฉันเองอย่างแม่นยำเกี่ยวกับระบบประเภท: C ++ แรกจากนั้นก็ Ocaml และตอนนี้เฟลิกซ์เป็นภาษาของฉันเอง ใช่ฉันยังคง refactor โดยไล่ตามข้อผิดพลาดของคอมไพเลอร์
Yttrill

8

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

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

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

ตรงข้ามของระบบพิมพ์แบบไดนามิกเป็นระบบแบบสแตติกไม่ใช่ระบบชนิดที่แข็งแกร่ง ระบบประเภทที่แข็งแกร่งอยู่ตรงข้ามกับระบบชนิดที่อ่อนแอ


1
ตัวอย่างเช่น C เป็นแบบสแตติก แต่พิมพ์อย่างอ่อน คุณมีประเภท แต่มันง่ายที่จะล้มล้างระบบการเรียงพิมพ์อย่างสมบูรณ์เล่นกับการแสดงเฉพาะเครื่องต้นแบบเป็นต้นภาษาที่พิมพ์แบบไดนามิกจำนวนมาก OTOH มีการพิมพ์ที่ค่อนข้างแรง
Steve314

4

มันจะบอกคุณทันทีเมื่อคุณทำผิดพลาดโง่ สิ่งนี้มีประโยชน์ ฉันทำงานใน Racket (Scheme) คำสุดท้ายนี้และมีหลายครั้งที่ฉันได้ผ่าน s-exp ที่ไม่ได้แยกวิเคราะห์ซึ่งฉันคาดว่าจะมีการแยกวิเคราะห์ ast กับฟังก์ชั่นบางอย่างในล่ามของฉันและมันปรากฏขึ้นเฉพาะใน ชุดทดสอบขนาดกลาง หากฉันมีการพิมพ์แบบคงที่มันจะถูกนำมาให้ความสนใจของฉันทันที

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

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

ความบริสุทธิ์ของ Haskell นั้นถูกเข้ารหัสในระบบชนิดของมัน IO monad เป็นโครงสร้างระดับประเภทที่หยุดการไม่บริสุทธิ์ของรหัสจากการรั่วไหลในฟังก์ชั่นที่แท้จริงดังนั้นความบริสุทธิ์จะถูกประกันโดยระบบประเภท


8
หากคุณคิดว่าคุณไม่สนใจระบบประเภทของ Haskell ฉันคิดว่าคุณไม่ได้เข้ารหัส Haskell มากนัก
Eric Wilson

อย่าเพิกเฉยเท่าที่เพิกเฉยมันออกไปพิมพ์ฟังก์ชั่นโหลดมันใน GHCi และไปที่: t แต่คุณยังจะต้องโรยในบางส่วนจากอินทราเน็ตหรือฟังก์ชั่นอื่น ๆ ในบางครั้ง
Theo Belaire

1
Tyr ถึงแม้จะมีการอนุมานประเภท 90% ของการใช้งานและการเข้ารหัสฟังก์ชัน Haskell กำลังทำให้สิ่งที่ถูกสาปเข้าด้วยกันซึ่งต้องมีความเข้าใจในระบบประเภทของมัน แม้แต่ ": t" ไม่ใช่โซลูชันที่น่าอัศจรรย์เพียงขั้นตอนแรกในการทำความเข้าใจวิธีการคอมไพล์โปรแกรม
Andres F.

บางส่วนยุ่งผมเห็นด้วย ฉันคิดจริงๆว่าสิ่งที่เป็นตัวเลขในโหมโรงสามารถยืนขึ้นเพื่อทำความสะอาดและแก้ไขเพราะมันเป็นสิ่งที่แย่มาก แต่หน้าที่หลัก ๆ ส่วนใหญ่นั้นค่อนข้างสะอาด แผนที่ตัวกรอง foldr / l และฟังก์ชั่นการใช้งานที่สนุกสนานอื่น ๆ ทำงานได้ค่อนข้างดี
Theo Belaire

2

เป็นภาษาที่ "ใช้งานได้" หมายถึง (นอกเหนือจากสิ่งอื่น ๆ ) ที่ฟังก์ชั่นเป็นวัตถุชั้นหนึ่งในภาษา

เป็น "บริสุทธิ์" หมายถึงภาษาที่ฟังก์ชั่นที่มีฟังก์ชั่นทางคณิตศาสตร์ (เมื่อเทียบกับขั้นตอน) - ได้รับการป้อนข้อมูลเดียวกันพวกเขามักจะผลิตออกเดียวกัน

"ฟังก์ชั่นภาษาบริสุทธิ์" เป็นภาษาที่ทั้งสองข้างต้นค้างไว้ ผมไม่ทราบของ "pure- Lyภาษาทำงาน"

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

หากระบบการพิมพ์รบกวนคุณฉันขอแนะนำให้คุณลองใช้ภาษาแบบไดนามิกมากขึ้นเช่น Scheme หรือหลีกเลี่ยงการใช้ระบบอนุมานประเภท Haskell


0

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

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