ใช้ระบบพิมพ์ที่“ แข็งแกร่ง” ในโลกแห่งความเป็นจริงพูดสำหรับเว็บแอปขนาดใหญ่หรือไม่?


29

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

บริบทโดยรวมของคำถาม

เราได้สร้างเว็บแอปขนาดใหญ่ขึ้นใน Ruby on Rails และโดยทั่วไปเรามีความสุขกับกองซ้อนของเรา เมื่อเราต้องการเราสามารถจัดส่งสิ่งต่าง ๆ ได้อย่างรวดเร็วจริง ๆ - สิ่งที่ใช้งานได้ 90% ของคดี "ธุรกิจ" โดยไม่ต้องกังวลเรื่องขอบคดีมากถึง 10% ในทางกลับกันด้วยความช่วยเหลือในการใช้โค้ดรีวิวและทดสอบครอบคลุมเราจะช้าและพิจารณาและตรวจสอบให้แน่ใจว่าเราครอบคลุมฐานทั้งหมด - อีกครั้งเฉพาะในสถานการณ์ที่สมควรได้รับการตรวจสอบข้อเท็จจริงและความปลอดภัยอย่างใกล้ชิด

อย่างไรก็ตามเมื่อทีมเติบโตขึ้นฉันเริ่มรู้สึกไม่สบายใจกับการขาด "ตาข่ายนิรภัย" ที่ถูกอบเข้าไปในกองของเรา

เราเพิ่งเริ่มทำการพัฒนา Android พื้นเมืองบน Java และฉันก็นึกถึงความปลอดภัยที่จัดเตรียมโดยภาษาที่รวบรวม / คงที่ / พิมพ์ดีดอย่างยิ่ง

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

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

ตอนนี้คำถาม

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

ตัวอย่างเช่นฉันจะก้าวออกไปนอกเหนือจากการแนะนำแบบ "สวัสดีโลก" ในฟีเจอร์ที่ทรงพลังเหล่านี้ได้อย่างไร หนึ่งที่ใช้ระบบ AA ริชประเภทเพื่อสร้างปัญหาโดเมนธุรกิจ? ระบบชนิดช่วยหรือขัดขวางเมื่อคุณอยู่ในโซน 30,000 LOC + หรือไม่ เกิดอะไรขึ้นกับเครือข่ายความปลอดภัยที่มีให้โดยระบบประเภทเหล่านี้ (และการตรวจสอบเวลาแบบคอมไพล์) เมื่อระบบของคุณโต้ตอบกับโลกภายนอกที่พิมพ์ออกมาอย่างอ่อนเช่น ผ่าน JSON หรือ XML APIs ที่เก็บข้อมูลต่าง ๆ อินพุตของผู้ใช้ ฯลฯ


12
นี่เป็นหัวข้อนอกเพราะไม่มีคำตอบที่แท้จริง คำถามนี้มีจุดประสงค์เพื่อกระตุ้นการอภิปรายดื้อดึง ( "ฉันชอบ / ไม่ชอบประเภทคงที่เพราะ ...") ไม่ได้คำอธิบายที่เป็นข้อเท็จจริง คำแนะนำของฉันคือเลือกส่วนที่เฉพาะเจาะจงของคำถามของคุณเช่น "จะเกิดอะไรขึ้นกับระบบความปลอดภัยที่จัดทำโดยระบบประเภทเหล่านี้เมื่อระบบของคุณโต้ตอบกับผู้ที่อ่อนแอนอกโลก" และเขียนคำถามใหม่เกี่ยวกับเรื่องนั้น คุณจะได้รับคำตอบที่ชัดเจนซึ่งจะเป็นประโยชน์ต่อผู้อ่านในอนาคต
Benjamin Hodgson

5
คำแนะนำเกี่ยวกับทรัพยากรเป็นหัวข้อนอกที่นี่ด้วย (เพราะคำตอบดังกล่าวล้าสมัยอย่างรวดเร็วและเราก็ไม่ได้ดีไปกว่า Google จริงๆ) ดังที่เบนจามินกล่าวว่ามีคำถามที่ตอบได้ถูกฝังอยู่ในโพสต์ของคุณ แต่โพสต์ทั้งหมดในสถานะปัจจุบันของมันคือการขอให้ผู้คนอธิบายประสบการณ์ของพวกเขาโดยใช้ภาษาเหล่านี้ซึ่งเหมาะสำหรับ Quora หรือ Reddit เว็บไซต์. ฉันไม่ได้ลงคะแนนเพราะคำถามนี้ได้รับการถามเป็นอย่างดี แต่มันไม่ใช่คำถาม StackExchange
Ixrec

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

5
สิ่งที่คุณอธิบายส่วนใหญ่ไม่มีส่วนเกี่ยวข้องกับระบบพิมพ์ เป็นฟีเจอร์ IDE ล้วนๆ ด้วยข้อยกเว้น (ไม่มีการเล่นสำนวนเจตนา) ของข้อยกเว้นที่ถูกตรวจสอบคุณสมบัติทั้งหมดที่คุณกล่าวถึงมีอยู่ใน Smalltalk IDEs นานก่อนที่จะปรากฏใน IDEs สำหรับภาษาที่พิมพ์แบบคงที่ ในความเป็นจริงหนึ่งใน Java IDEs ที่ใช้กันอย่างแพร่หลายเริ่มจริงแล้วเป็น Smalltalk IDE ที่แก้ไขแล้ว (IBM VisualAge Smalltalk ซึ่งได้รับการแก้ไขเพื่อให้เข้าใจโค้ด Java แต่ยังเขียนใน Smalltalk และเผยแพร่เป็น VisualAge Java ซึ่งถูกส่งไปยัง Java และเปิดตัวเป็น ...
Jörg W Mittag

4
… VisualAge Java Micro Edition ซึ่งถูกแบ่งออกเป็นส่วนประกอบที่ใช้งานได้อีกครั้งและเปิดตัวเป็นโอเพ่นซอร์สภายใต้ชื่อ Eclipse) ค่อนข้างในแง่ของคำถามนี้มันเป็นเรื่องจริงเพราะธรรมชาติของระบบ Smalltalk ไดนามิกที่ Smalltalk IDEs นั้นทรงพลังมาก Refactorings อัตโนมัติถูกคิดค้นและนำไปใช้เป็นครั้งแรกใน Smalltalk ตามตรรกะของคุณ Haskell จะต้องมี IDE ที่ดีที่สุดเนื่องจากมีระบบพิมพ์คงที่ที่แข็งแกร่งและเข้มงวดที่สุดของทุกภาษาที่คุณพูดถึง แต่มันก็ไม่ได้ คุณยังพูดถึง "hooking the compiler" นี่คือ ...
Jörg W Mittag

คำตอบ:


34

ฉันจะให้คำตอบสั้น ๆ เนื่องจากไม่มีเวลาในขณะนี้ แต่ฉันกำลังทำงานในสองโครงการใหญ่ (> 100.000 LOC ใน Haskell) - flowbox.ioและluna-lang.org. เราใช้ Haskell สำหรับชิ้นส่วนทั้งหมดรวมถึงแบ็กเอนด์คอมไพเลอร์ของภาษาการเขียนโปรแกรมของเราและแม้กระทั่ง GUI ที่ใช้ webGL ฉันต้องยอมรับว่าระบบการพิมพ์ที่แข็งแกร่งและเครื่องจักรที่คล้ายกัน "ขึ้นอยู่กับประเภท" สามารถแนะนำคุณและช่วยให้คุณประหยัดจากภาระและความยุ่งยากที่รู้จักจากภาษาอื่น ๆ เราใช้ประเภทต่างๆอย่างกว้างขวางและทุกอย่างที่สามารถตรวจสอบได้ในเวลารวบรวมนั้นทำได้ ในความเป็นจริงในช่วง 3 ปีของการพัฒนาเราไม่เคยพบข้อผิดพลาดรันไทม์หรือสแต็กมากเกินไป (และนี่คือสิ่งที่เหลือเชื่อจริงๆ) ข้อผิดพลาดเพียงอย่างเดียวคือข้อผิดพลาดทางตรรกะที่ชัดเจนโดยโปรแกรมเมอร์ ผู้คนมากมายบอกว่าถ้ามีบางอย่างในฮัสเซลล์ก็ใช้ได้ดีและคุณน่าจะแน่ใจว่ามันจะไม่กระทบกับใบหน้าของคุณในบางวัน

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

ในความเป็นจริงมีบล็อกที่น่าสนใจอื่น ๆ อีกมากมายอยู่ (เช่นดาวเคราะห์ Haskell ) อย่างไรก็ตามวิธีที่ดีที่สุดในการเข้าใจระบบประเภทขั้นสูงคือการพัฒนาไลบรารีโอเพ่นซอร์สที่มีประโยชน์ เรา (ที่ Flowbox & New Byte Order) กำลังเปิดตัวห้องสมุดจำนวนมาก (คุณสามารถค้นหาได้ที่ Hackage) ดังนั้นหากคุณไม่มีความคิดว่าจะพัฒนาอะไรคุณสามารถมีส่วนร่วมในโครงการของเรา - เพียงส่งอีเมลถึงฉันทุกครั้งที่คุณ ต้องการ (มีอีเมลที่luna-lang.org )


4
"มีคนจำนวนมากบอกว่าถ้ามีบางสิ่งในคอมไพล์ใน Haskell มันใช้งานได้และคุณน่าจะแน่ใจได้ว่ามันจะไม่กระทบกับใบหน้าของคุณในแต่ละวัน": ฉันเคยใช้ Haskell ในโครงการขนาดเล็ก (แม้ว่าไม่ใช่เรื่องเล็กน้อย) แต่ฉันสามารถยืนยันสิ่งนี้: เมื่อคอมไพเลอร์ Haskell พอใจฉันไม่ค่อยพบข้อบกพร่องใด ๆ
Giorgio

1
ฉันอาจเป็นหนึ่งในพวก "Haskell" ที่เกลียดประเภทมากที่สุด (มากฉันเขียนHaskell รุ่นที่ไม่มีประเภท ) - แต่ด้วยเหตุผลที่แตกต่างกันที่คนส่วนใหญ่ทำ เมื่อพูดถึงวิศวกรรมซอฟต์แวร์ฉันก็รู้สึกเช่นนั้นเมื่อ GHC มีความสุขโปรแกรมของคุณก็ใช้ได้เช่นกัน ระบบประเภท Haskell นั้นเป็นเครื่องมือที่ดีที่สุดไม่เพียง แต่สำหรับการตรวจจับความผิดพลาดอย่างมีมนุษยธรรมในการเขียนโปรแกรม แต่สำหรับการรักษาฐานรหัสขนาดใหญ่ภายใต้การควบคุมของคุณ (ฉันจำได้เสมอว่าเหตุผลของ Giovanni ต่อชุดเกราะของ Mewtwo เมื่อใดก็ตามที่ฉันต้องแก้ไขความผิดพลาดประเภท)
MaiaVictor

บล็อกของ Gabriel Gonzales ดีที่สุดในการเริ่มต้นด้วย
sam boosalis

@ danilo2 ได้ส่งอีเมลไปยังที่อยู่ contact @ บนเว็บไซต์ บริษัท ของคุณแล้ว ขอให้คุณตอบกลับ ขอบคุณ!
Saurabh Nanda

@SaurabhNanda: ฉันตรวจสอบกล่องจดหมายของเราสองครั้งและฉันไม่เห็นข้อความใด ๆ จากคุณ คุณส่งไปให้ติดต่อ <at> luna-lang.org หรือไม่ โปรดติดต่อฉันโดยตรงที่เขียนถึงวอยจอย <dot> danilo <at> gmail <dot> com ของเราและเราจะตรวจสอบสาเหตุของปัญหานี้ :)
danilo2

17

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

ดังนั้นฉันชอบคำจำกัดความ:

  • ระบบที่พิมพ์อ่อนแอใช้ประเภทเพื่อป้องกันคุณจากการทำบางสิ่ง (เช่นความผิดพลาด)
  • ระบบที่พิมพ์อย่างรุนแรงใช้ประเภทเพื่อทำสิ่งต่าง ๆ ให้คุณ

ฉันหมายความว่ายังทำอะไรให้คุณ เรามาตรวจสอบการเขียน API การแปลงอิมเมจในเฟรมเวิร์กของ Servant (ใน Haskell แต่คุณไม่จำเป็นต้องรู้ให้ทำตามคุณจะเห็น ... )

{-# LANGUAGE
    TypeOperators,
    DataKinds
    #-}

import Codec.Picture
import Data.Proxy
import Network.Wai.Handler.Warp (run)
import Servant
import Servant.JuicyPixels

main :: IO ()
main = run 8001 conversion

นี่คือการบอกว่าเราต้องการโมดูลบางอย่างรวมถึงแพคเกจ Servant และปลั๊กอิน JuicyPixels ให้กับ Servant และจุดเริ่มต้นหลักของโปรแกรมคือการเรียกใช้ฟังก์ชั่น 'การแปลง' บนพอร์ต 8001 เป็นเซิร์ฟเวอร์โดยใช้แบ็กเอนด์ Warp ละเว้นบิตภาษา

conversion :: Application
conversion = serve (Proxy :: Proxy ConversionApi) handler

นี่คือการพูดว่าฟังก์ชั่นการแปลงเป็นเซิร์ฟเวอร์ที่ API ต้องตรงกับประเภท 'ConversionApi' และฟังก์ชั่นการจัดการที่ร้องขอ handler

type ConversionApi
     = ReqBody '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage
    :> Post '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] DynamicImage

นี่เป็นการระบุConvesionApiประเภท มีข้อความระบุว่าเราควรยอมรับประเภทเนื้อหาขาเข้าที่ระบุโดยรายการ '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE] และจัดการเป็น DynamicImage และเราควรคืนค่า DynamicImage ที่แปลงเป็นช่วงเนื้อหาเดียวกัน ประเภท ไม่ต้องกังวลกับสิ่งที่:> หมายถึงแค่คิดว่ามันเป็นเวทมนตร์ที่มีความสุขในตอนนี้

ดังนั้นตามคำจำกัดความที่ฉันต้องการระบบที่พิมพ์อย่างอ่อนแอสามารถมั่นใจได้ในสิ่งต่อไปนี้:

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

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

handler = return

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

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

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

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

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

อย่างดีที่สุดที่ฉันสามารถนำเสนอประเภทสามารถแบ่งชั้นได้เช่น:

  • พิมพ์อย่างอ่อนมากสิ่งต่างๆเช่น JavaScript ที่ [] + {} ถูกกำหนดไว้
  • พิมพ์อย่างอ่อนแอเช่น Python ซึ่งคุณไม่สามารถทำ [] + {} ได้ แต่จะไม่ถูกตรวจสอบจนกว่าคุณจะลอง
  • พิมพ์อ่อนแอเช่น C หรือ Java ซึ่งคุณไม่สามารถทำ [] + {} ได้ แต่ตรวจสอบเวลารวบรวมแล้ว แต่คุณไม่มีคุณสมบัติประเภทขั้นสูงเพิ่มเติม
  • คร่อมขอบระหว่างการพิมพ์ที่อ่อนแอและรุนแรงเช่นเทมเพลต C ++ เทมเพลตการเขียนโปรแกรมและรหัส Haskell ที่ง่ายขึ้นโดยที่ประเภทจะบังคับใช้คุณสมบัติเท่านั้น
  • พิมพ์ลงในกล่องข้อความอย่างแน่นหนาเช่นโปรแกรม Haskell ที่มีความซับซ้อนมากกว่า
  • การพิมพ์ที่รุนแรงมากเช่น Agda หรือ Idris ที่ประเภทและค่าโต้ตอบและสามารถ จำกัด ซึ่งกันและกัน สิ่งนี้มีความแข็งแกร่งพอ ๆ กับระบบการพิมพ์และการเขียนโปรแกรมในนั้นเหมือนกับการเขียนหลักฐานทางคณิตศาสตร์เกี่ยวกับโปรแกรมของคุณ หมายเหตุ: การเขียนโปรแกรมใน AGDA มันไม่ได้เป็นตัวอักษรเขียนบทพิสูจน์ทางคณิตศาสตร์ประเภททฤษฎีทางคณิตศาสตร์และฟังก์ชั่นที่มีชนิดที่เป็นตัวอย่างที่สร้างสรรค์พิสูจน์ทฤษฎีเหล่านั้น

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


โปรดทราบว่าคุณไม่จำเป็นต้องนำหน้ารายการระดับประเภทด้วยเครื่องหมายอัญประกาศเดี่ยวหากมีองค์ประกอบมากกว่าในรายการ เครื่องหมายอัญประกาศเดี่ยวมีความจำเป็นสำหรับรายการระดับประเภท 0- หรือ 1 องค์ประกอบเนื่องจากมีความคลุมเครือ (อาจหมายถึงตัวสร้างประเภทรายการทั่วไป)
Gabriel Gonzalez

1
ฉันรู้ แต่ฉันรู้สึกว่าเครื่องหมายวรรคตอนเป็นรูปแบบที่ดีสำหรับประเภทข้อมูลที่ได้รับการประชาสัมพันธ์โดยทั่วไป EG ที่Proxy :: Proxy Trueประพฤติ Proxy :: Proxy 'Trueแต่มันจะดีกว่าที่จะเขียนมันเป็น
Steven Armstrong

1
ดูเหมือนว่าจะไม่ยุบแกนต่าง ๆ ตามประเภทของระบบที่สามารถจำแนกได้ แลมบ์ดาแลมบ์ดาของ Barendregt มีอยู่สามแบบและนอกจากนี้ตามแกนที่อ่อนแอ - ที่แข็งแกร่งที่คุณยังรวมถึงแบบคงที่กับแบบไดนามิกและแบบไดนามิกและแบบพาราเมตริกเมื่อเทียบกับแบบ Adhoc polymorphism ')
user2141650

1
จุดประสงค์ แต่คำตอบนั้นยาวมากแล้วและคุณจะต้องเรียนรู้ทฤษฎีประเภทก่อนที่แลมบ์ดาคิวบ์จะเริ่มรู้สึกดี นอกจากนอกซอกมาก (และเนื่องจากฉันรวม Haskell และ Agda แล้วฉันหมายถึงโพรงค่อนข้างมาก ) คุณไม่ได้ไปหาภาษาที่มียกตัวอย่างเช่นประเภทพึ่งพา แต่ไม่มีตัวดำเนินการประเภท .
Steven Armstrong

คุณสามารถอธิบาย'[xs]ไวยากรณ์โดยย่อได้หรือไม่? สิ่งนี้ไม่ชัดเจนCharแต่ฉันไม่เห็นว่าจะเปิดใช้งานTypeOperatorsหรือDataKindsเปิดใช้งานไวยากรณ์อื่นได้อย่างไร มันเป็น quasiquoting บางชนิด?
wchargin

10

ฉันเพิ่งเริ่มทำงานกับทีมหลักของแพลตฟอร์มขนาดใหญ่ที่เขียนใน Scala คุณสามารถดูแอปพลิเคชันโอเพ่นซอร์สที่ประสบความสำเร็จเช่น Scalatra, Play หรือ Slick เพื่อดูว่าพวกเขาจัดการกับคำถามที่มีรายละเอียดเพิ่มเติมเกี่ยวกับการโต้ตอบกับรูปแบบข้อมูลแบบไดนามิกได้อย่างไร

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

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

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

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

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

ข้อเสียเปรียบหลักคือไม่คุ้นเคยกับภาษาและกระบวนทัศน์ทางภาษาและแก้ไขได้ตามเวลา อื่น ๆ ที่เราพบว่ามันคุ้มค่ากับความพยายาม


8

แม้ว่าจะไม่ใช่คำตอบโดยตรง (เนื่องจากฉันยังไม่ได้ใช้งานฐานรหัส LOC มากกว่า 30,000 ชุดใน Haskell เลย :( .. ) ฉันขอให้คุณลองดูhttps://www.fpcomplete.com/business/resources/case-studies /ซึ่งมีกรณีศึกษาจำนวนมากของ Haskell ในการตั้งค่าอุตสาหกรรมจริง

บทความดีดีอีกประการหนึ่งคือ IMVU ที่อธิบายประสบการณ์ของพวกเขาเปลี่ยนไป Haskell - http://engineering.imvu.com/2014/03/24/what-its-like-to-use-haskell/

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

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

เกี่ยวกับการจัดการกับโลกภายนอกนั้นทำได้หลายวิธี มีห้องสมุดเพื่อให้แน่ใจว่าสิ่งที่คุณต้องทำนั้นปลอดภัยเช่นAesonสำหรับ JSON, Esqueletoสำหรับ SQL และอีกมากมาย


1
ขอบคุณสำหรับคำตอบอย่างไรก็ตามกรณีศึกษาในfpcomplete.com/business/resources/case-studiesจะไม่สามารถใช้ได้อีกต่อไป
Saurabh Nanda

ดูเหมือนว่ากรณีศึกษาถูกย้ายไปที่fpcomplete.com/case-study
Steven Shaw

3

สิ่งที่ฉันเคยเห็น:

ฉันได้ทำงานกับเว็บแอพพลิเคชั่น Ruby (Rails) ขนาดใหญ่, เว็บแอพพลิเคชั่น Haskell ขนาดใหญ่หนึ่งอัน, และอันที่เล็กกว่าอีกหลายตัว ด้วยประสบการณ์นั้นฉันต้องบอกว่าชีวิตที่ทำงานกับแอพพลิเคชั่น Haskell นั้นง่ายกว่าใน Rails ในแง่มุมต่างๆเช่นการบำรุงรักษาและช่วงการเรียนรู้ที่ลดลง ฉันเห็นว่าประโยชน์เหล่านี้มีทั้งเนื่องจากระบบประเภทของ Haskell และรูปแบบการเขียนโปรแกรมที่ใช้งานได้ อย่างไรก็ตามแตกต่างจากหลาย ๆ ฉันเชื่อว่าส่วน "คงที่" ของระบบประเภทเป็นเพียงความสะดวกสบายอย่างมากในการที่ยังคงมีประโยชน์ที่จะมีเมื่อใช้สัญญาแบบไดนามิก

สิ่งที่ฉันเชื่อ

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

ตอบคำถาม

เพื่อตอบคำถามที่ถูกโพสต์ไว้ข้างต้นมีหลายสถานที่ที่เราสามารถทำความคุ้นเคยกับ Haskell และภาษาอื่น ๆ ด้วยระบบการพิมพ์ขั้นสูง อย่างไรก็ตามและเพื่อความซื่อสัตย์อย่างสมบูรณ์แบบในขณะที่แหล่งเอกสารเหล่านี้ยอดเยี่ยมในสิทธิของตนเองพวกเขาทั้งหมดดูค่อนข้างน้อยเมื่อเทียบกับเอกสารมากมายและคำแนะนำการปฏิบัติที่พบใน Ruby, Python, Java และภาษาอื่น ๆ ไม่ว่าในกรณีใดก็ตามReal World Haskellอายุมาก แต่ก็ยังเป็นทรัพยากรที่ดี

ทฤษฎีหมวดหมู่

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

เพิ่มเติมเกี่ยวกับประเภท

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


2

ก่อนอื่นฉันรู้สึกว่ามีความสับสนในคำตอบระหว่างการพิมพ์ที่ไม่รุนแรงและการพิมพ์ที่รุนแรงและการพิมพ์แบบคงที่และแบบไดนามิก ลิงก์ OP ที่จัดเตรียมไว้อย่างชัดเจนทำให้ความแตกต่าง:

ระบบชนิดที่รัดกุมคือระบบชนิดที่มีข้อ จำกัด ในการคอมไพล์หรือคุณลักษณะเวลาทำงานที่คุณพบว่าน่าสนใจ

ระบบประเภทที่อ่อนแอเป็นระบบประเภทที่ไม่มีข้อ จำกัด หรือคุณสมบัติดังกล่าว

ตัวอย่างเช่น C, C ++ และ Java ถูกพิมพ์แบบคงที่เนื่องจากตัวแปรถูกพิมพ์ ณ เวลารวบรวม แต่ C และ C ++ นั้นสามารถพิมพ์ได้อย่างอ่อนเนื่องจากภาษายอมให้มีการข้ามข้อ จำกัด โดยใช้พvoid *อยน์เตอร์และ casts เพิ่มเติมในหัวข้อนี้

ในความแตกต่างนี้การพิมพ์ที่แข็งแกร่งสามารถทำได้ดีกว่าเท่านั้น ก่อนหน้านี้ล้มเหลวที่ดีกว่า

อย่างไรก็ตามในการเขียนโปรแกรมขนาดใหญ่ฉันไม่คิดว่าระบบประเภทมีบทบาทสำคัญ เคอร์เนลลินุกซ์คือสิบล้าน LOC ที่เขียนด้วย C และแอสเซมบลีและถือว่าเป็นโปรแกรมที่เสถียรมากมันอยู่ห่างจาก 200 สาย Java ของฉันที่อาจเต็มไปด้วยช่องโหว่ด้านความปลอดภัย ในทำนองเดียวกันแม้ว่า "ภาษาสคริปต์" ที่พิมพ์แบบไดนามิกจะได้รับชื่อเสียงที่ไม่ดีเมื่อพูดถึงการเขียนโปรแกรมขนาดใหญ่ แต่บางครั้งก็พิสูจน์ได้ว่ามันไม่สมควร (เช่น Python Django มากกว่า 70k LOC)

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


-1

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

จากคำตอบก่อนหน้าhttps://www.fpcomplete.com/business/resources/case-studies/

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

มันเหมือนภาษาอื่นใด ๆ เพื่อสร้างความแข็งแกร่ง

เราจะใช้ระบบชนิดที่มีรูปแบบหลากหลายเพื่อสร้างแบบจำลองปัญหาโดเมนธุรกิจได้อย่างไร

โดยใช้ Abstract Data Types หรือมากกว่าpolymorphism

ระบบชนิดช่วยหรือขัดขวางเมื่อคุณอยู่ในโซน 30,000 LOC + หรือไม่

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

PS: อย่าทำผิดพลาดในการมีระบบการพิมพ์และต้องเขียนตัวเองซึ่งเป็นคนงี่เง่า: คอมพิวเตอร์สามารถทำเพื่อคุณ

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

มันเยี่ยมมากเมื่อทราบว่าโครงสร้างของค่าผ่านประเภทหมายความว่าคอมพิวเตอร์สามารถอนุมานวิธีในการเขียน (de) serializer สำหรับคุณ

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

มันเป็นกระดาษไม่ใช่กรณีศึกษาที่มีรูปภาพสวย ๆ แต่มันก็เป็นความสว่าง


-2

ในฐานะโปรแกรมเมอร์. net ที่ทำงานในเว็บแอปพลิเคชั่นมากมายฉันเห็นทั้ง C # ที่พิมพ์และด้าน Javascript ที่ไม่มีการพิมพ์

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

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

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


คุณหมายถึงการพิมพ์ / ไม่พิมพ์หรือพิมพ์แบบคงที่ / พิมพ์แบบไดนามิกหรือไม่? ไม่ได้พิมพ์ JavaScript แต่พิมพ์แบบไดนามิก
Giorgio

2
คุณไม่จำเป็นต้องกำหนดประเภท ภาษาที่เหมาะสมใด ๆ จะอนุมานประเภทของคุณ: Haskell, ocaml, sml, F # ...
nicolas

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