การพิมพ์ที่อ่อนแอและแข็งแรงนั้นค่อนข้างชัดเจน นอกจากนี้เนื่องจากใกล้เคียงกับการใช้งานโดยทั่วไปของ 'การพิมพ์ที่รัดกุม' คือการอ้างอิงสิ่งต่าง ๆ ที่ทำให้การพิมพ์เป็นเรื่องยากซึ่งไม่มีอะไรเพิ่มเติมที่จะอธิบายถึงระบบการพิมพ์ที่แข็งแกร่งยิ่งขึ้น มันเหมือนกับว่าถ้าคุณสามารถแบกน้ำหนักน้อยกว่า 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 มันไม่ได้เป็นตัวอักษรเขียนบทพิสูจน์ทางคณิตศาสตร์ประเภททฤษฎีทางคณิตศาสตร์และฟังก์ชั่นที่มีชนิดที่เป็นตัวอย่างที่สร้างสรรค์พิสูจน์ทฤษฎีเหล่านั้น
โดยทั่วไปยิ่งคุณลงรายการมากเท่าไหร่คุณก็ยิ่งสามารถทำตามประเภทนี้ได้ แต่ที่ด้านล่างสุดคุณกำลังปีนขึ้นสู่สตราโตสเฟียร์และอากาศกำลังเริ่มบางลง - ระบบนิเวศของแพ็คเกจนั้นเล็กกว่ามาก จะต้องเขียนสิ่งต่าง ๆ เพิ่มเติมด้วยตัวคุณเองเมื่อเจอห้องสมุดที่เกี่ยวข้อง อุปสรรคในการเข้ายังสูงขึ้นเมื่อคุณลงไปเนื่องจากคุณต้องเข้าใจระบบจริงมากพอที่จะเขียนโปรแกรมขนาดใหญ่ได้