- นักพัฒนาคนหนึ่งเปรียบเทียบความรู้สึกในการพัฒนาจริงของภาษาฟังก์ชันทั้งสองภาษา จากประสบการณ์ใช้ Haskell 8 ปี และ OCaml 8 เดือน ในโปรดักชัน
- Haskell มีไวยากรณ์ที่กระชับกว่าและความสามารถด้าน type ที่ทรงพลัง แต่เพราะมีตัวเลือกมาก จึงทำให้เสียสมาธิไปกับการออกแบบและ abstraction ได้ง่าย
- OCaml แม้จะมีฟีเจอร์น้อยกว่า แต่ถูกประเมินว่าโฟกัสกับการลงมือทำได้ง่ายกว่า ด้วย first-class modules ความสามารถในการเปลี่ยนแปลงค่าแบบใช้งานจริง และสไตล์โค้ดที่คาดเดาได้
- ระบบนิเวศของ Haskell ใหญ่กว่า แต่การเลือกไลบรารีอาจให้ความรู้สึกเหมือนเป็นทักษะเฉพาะอย่างหนึ่ง ส่วน OCaml แม้จะเล็กกว่า แต่เครื่องมือที่จำเป็นกลับใช้งานได้ดีกว่าที่คิด
- ทั้งสองภาษายังเล็กกว่าภาษากระแสหลัก และ standard library ก็ใกล้เคียงกับชุดขั้นต่ำ แต่ถ้าไม่ได้พึ่งพา SDK เฉพาะทางมากนัก ก็เพียงพอสำหรับการพัฒนาแอปในงานอุตสาหกรรม
จุดตั้งต้นของการเปรียบเทียบ
- เกณฑ์คือประสบการณ์ใช้ Haskell ในโปรดักชัน 8 ปี และ OCaml 8 เดือน
- แกนการเปรียบเทียบคือไวยากรณ์ ฟีเจอร์ภาษา ระบบนิเวศ เครื่องมือ ข้อความจากคอมไพเลอร์ และ standard library
- ทั้งสองภาษาพัฒนามาไกลพอจะรองรับความต้องการในอุตสาหกรรมจริง แต่ ณ ตอนนี้ผู้เขียนเอนเอียงไปทาง OCaml มากกว่า
ไวยากรณ์: Haskell กระชับกว่า และ OCaml ก็ยังมีจุดเด่นแบบสาย ML
- Haskell สามารถสื่อไอเดียได้ด้วยอักขระน้อยมาก ทำให้รู้สึกถึงความสง่างามของไวยากรณ์ได้อย่างชัดเจน
- OCaml ก็ยอดเยี่ยมเช่นกันในฐานะภาษา ตระกูล ML แต่ Haskell ให้สไตล์แบบ tacit ที่ชัดเจนกว่า
- ในตัวอย่างการหาผลรวมของตัวเลขในสตริง Haskell เขียนสั้น ๆ ได้เป็น
sum . map read . wordsส่วน OCaml จะระบุขั้นตอนแยกสตริง แปลงค่า และ fold ผ่าน pipeline อย่างชัดเจน - ตัวอย่างการนิยามชนิดข้อมูล binary tree แสดงให้เห็นว่าทั้งสองภาษาสามารถอธิบาย algebraic data types ได้อย่างเป็นธรรมชาติ
- ตัวอย่างการ parsing แสดงว่าทั้งสองภาษาใช้ pattern matching และ option values ได้เหมือนกัน แต่ Haskell ใช้ do notation กับ
guardขณะที่ OCaml ใช้Option.bindและmatchแบบชัดเจน
ฟีเจอร์: Haskell หลากหลายกว่า ส่วน OCaml วุ่นวายน้อยกว่า
- Haskell มีฟีเจอร์จำนวนมากมาก จนรู้สึกว่าคู่เทียบที่ใกล้เคียงอาจเป็น C++
- ฟีเจอร์จำนวนมากช่วยให้แก้ปัญหาได้อย่างประณีต แต่ก็อาจทำให้ต้องไปคิดเรื่องวิธีออกแบบคำตอบก่อนจะเริ่มลงมือทำจริง
- ใน Haskell มักหลงไปกับตัวเลือกอย่าง
TypeFamilies,DataKinds,GADTsได้ง่าย - สถานการณ์แย่ ๆ ในโปรเจกต์ OCaml ที่มีอยู่เดิม มักอยู่ในระดับชื่อแปรไม่ดี เอกสารไม่พอ หรือมีฟังก์ชันยาวเกิน 200 บรรทัด ซึ่งยังถือว่ารับมือได้
- ในทางกลับกัน โปรเจกต์ Haskell ที่มีอยู่เดิมอาจเจอ ความซับซ้อนที่แม้มีประสบการณ์ 8 ปีก็เตรียมตัวรับได้ยาก
- ด้วยความต่างนี้ ผู้เขียนจึงรู้สึกว่าตัวเองมีผลิตภาพมากกว่าเมื่อใช้ OCaml
-
ฟีเจอร์ที่ทั้งสองภาษามีร่วมกัน
- ทั้งคู่มีไวยากรณ์แบบยึด expression เป็นศูนย์กลาง immutable โดยพื้นฐาน higher-order functions anonymous functions algebraic data types และ pattern matching
- ทั้งคู่รองรับ parametric polymorphism, type inference, monadic syntax sugar, garbage collector, multithreading และ GADTs
-
ฟีเจอร์ที่เด่นกว่าทางฝั่ง Haskell
- Haskell มีความเป็น pure โดยปริยาย, lazy evaluation ที่ประกอบต่อกันได้, type classes, higher-kinded types และ language extensions แบบเลือกเปิดใช้ได้
- เมื่อมีฟีเจอร์ทรงพลังจำนวนมาก วิธีทำ abstraction ในแต่ละโปรเจกต์จึงอาจต่างกันมาก
-
ฟีเจอร์ที่เด่นกว่าทางฝั่ง OCaml
- OCaml มี first-class modules, polymorphic variants, objects, classes กับ inheritance และ mutability ที่ใช้งานได้ง่าย
- แม้ขอบเขตของฟีเจอร์จะแคบกว่า Haskell แต่ก็มีข้อดีคือทำให้คาดเดาโค้ดเบสได้ง่ายกว่า
ระบบนิเวศ: Haskell ใหญ่กว่า ส่วน OCaml ก็มีทางแก้ที่ต้องใช้
- ทั้งสองภาษาเป็นภาษาฟังก์ชันเฉพาะกลุ่ม จึงยากจะคาดหวังการรองรับระดับ first-class จากเฟรมเวิร์กล่าสุด
- ถึงอย่างนั้น งานทั่วไปส่วนใหญ่ก็ยังมีทางแก้ และบางกรณีอาจต้องเขียน custom bindings เพิ่มเอง
- ใน OCaml ก็ยังหาแพ็กเกจที่ใช้ในงานจริงได้ เช่น
- otoml: ตัว parser สำหรับ TOML
- Mint Tea: เฟรมเวิร์ก TUI
- ocaml-opentelemetry: เครื่องมือทำ OpenTelemetry instrumentation
- awsm: ไคลเอนต์ AWS สำหรับ OCaml
- petrol: SQL API สำหรับ OCaml ที่รวดเร็ว
- ระบบนิเวศของ Haskell มีทั้งแพ็กเกจและโซลูชันพร้อมใช้มากกว่า
- ไลบรารีไคลเอนต์สำหรับ Stripe API มีใน Haskell 13 ตัว ส่วน OCaml มี 1 ตัว และฝั่ง OCaml นั้นไม่ได้อัปเดตมา 8 ปีแล้ว จึงแทบจะนับว่าเหลือ 0
- ใน Haskell ต่อให้หาโซลูชันเจอแล้ว ก็ยังต้องตัดสินใจว่าจะเลือกไลบรารีไหนจาก ตัวเลือกที่มากเกินไป
- ถึงขั้นมีบทความสรุป วิธีประเมินไลบรารี เพราะการเลือกไลบรารีแทบกลายเป็นทักษะแยกต่างหาก
- ไลบรารี Haskell ใหม่ ๆ หลายตัวเกิดขึ้นไม่ใช่เพราะจะแก้ปัญหาใหม่ แต่เพราะอยากเขียนสิ่งเดิมด้วย abstraction แบบอื่นหรือเพิ่มฟีเจอร์ใหม่
- บางครั้งการ ออกแบบ logger ด้วย comonads อาจน่าสนใจกว่าการสร้าง GitHub API client หรือการ parse JSON จำนวนมากเสียอีก
เครื่องมือ: Haskell ทรงพลังแต่ขึ้น ๆ ลง ๆ ส่วน OCaml ใช้งานได้ดี
- เครื่องมือของ Haskell มีทั้งจุดแข็งที่ทรงพลังและปัญหาด้าน usability อยู่พร้อมกัน
- Hoogle เป็นเครื่องมือทรงพลังที่ค้นหาทั้งระบบนิเวศได้จาก type signature เพียงอย่างเดียว
- แต่ในอีกด้านก็มีปัญหาอย่างข้อความ error จาก build tool, สถานการณ์ที่หา build plan ไม่เจอทั้งที่โปรเจกต์ใช้งานอยู่, IDE ต้อง recompile หลังเปลี่ยนแพ็กเกจ หรือไม่มีเอกสารของ standard library สำหรับบางเวอร์ชันโดยเฉพาะ
- ประสบการณ์ใช้เครื่องมือ Haskell จึงมีทั้งช่วงที่แปลกใจว่าภาษาอื่นใช้งานกันได้อย่างไรโดยไม่มีเครื่องมือแบบนี้ และช่วงที่แปลกใจว่าผู้ใช้ Haskell อยู่กันมาได้อย่างไรโดยไม่มี usability พื้นฐานบางอย่าง
- OCaml มีระบบนิเวศเล็กกว่า จึงยิ่งน่าแปลกใจทุกครั้งที่พบว่าสิ่งต่าง ๆ ใช้งานได้จริง
- ปลั๊กอิน VSCode OCaml ที่อิง LSP ทำงานได้โดยไม่ต้องปรับแต่งเพิ่มเติมและไม่พบปัญหา
- แม้ประสบการณ์เริ่มต้นกับเครื่องมือ OCaml จะไม่ถึงขั้นสะดวกที่สุด แต่ก็ตรงไปตรงมา แข็งแรง และโดยมากทำงานได้ถูกต้อง
-
เปรียบเทียบเครื่องมือ
- คอมไพเลอร์: OCaml คือ ocaml, Haskell คือ ghc
- REPL: OCaml คือ utop, Haskell คือ ghci
- เครื่องมือ build: OCaml คือ dune, Haskell คือ cabal และ stack
- package manager และ repository: OCaml คือ opam, Haskell คือ cabal และ Hackage
- linter: OCaml คือ zanuda, Haskell คือ hlint
- formatter: OCaml คือ ocamlformat และ topiary, Haskell คือ fourmolu, stylish-haskell, hindent, ormolu
- การค้นหา type และค้นหาโค้ด: OCaml คือ Sherlodoc และ Sherlocode, Haskell คือ Hoogle และ Hackage Search
- playground ออนไลน์และ LSP: OCaml คือ TryOCaml และ ocaml-lsp, Haskell คือ Haskell Playground และ HLS
ข้อความจากคอมไพเลอร์: Haskell ยืดยาว ส่วน OCaml กระชับ
- ในภาษาฟังก์ชัน คอมไพเลอร์คือเครื่องมือสำคัญในการทำความเข้าใจว่าทำไมโค้ดจึงไม่เป็นไปตามสมมติฐานที่ตั้งใจไว้
- เพราะฉะนั้น ข้อความ error ควรแสดงข้อมูลที่จำเป็นในรูปแบบที่เข้าถึงได้ง่าย
- ข้อความจากคอมไพเลอร์ของ Haskell มักมีบริบทจำนวนมาก ยาว และมีข้อมูลที่ซ้ำซ้อนหรือทำให้เสียสมาธิ
- ข้อความจากคอมไพเลอร์ของ OCaml ค่อนข้างกระชับ และบางครั้งก็ กระชับเกินไป
- โปรแกรมตัวอย่างที่ทำให้ error คือโค้ดที่พยายามบวกจำนวนเต็มกับลิสต์ เช่น
x = 1 + [3, 1, 2]ใน Haskell และlet x = 1 + [3; 1; 2]ใน OCaml
Standard library: ทั้งคู่มีมาให้น้อย และคุณภาพเอกสารของ Haskell เด่นกว่า
- standard library เป็นสิ่งที่กำหนดทั้งประสบการณ์เขียนโปรแกรมแรกเริ่มและการใช้งานหลังจากนั้น
- standard library ที่ดีคือรากฐานของความสำเร็จของภาษาโปรแกรม ส่วน standard library ที่ไม่พออาจทำให้เกิดข้อถกเถียงเรื่องไลบรารีมาตรฐานทางเลือกได้เรื่อย ๆ
- ผู้เขียนมองว่า standard library ที่พึงประสงค์ควรใกล้เคียงแนวทางแบบ batteries-included
- สิ่งที่อยากให้มี ได้แก่ type แบบ Option, สตริง UTF-8, Map และ HashMap, parser สำหรับ JSON และ XML, async primitives เป็นต้น
- หากไม่อยากต้องไปเรียนรู้การทำงานของ build tools และระบบติดตาม dependencies ก็ควรมีความสามารถใน standard library ให้มากกว่านี้
- Build Systems a la Carte เป็นเอกสารที่วิเคราะห์พื้นที่ของตัวติดตาม dependencies และเครื่องมือ build
- ทั้ง Haskell และ OCaml ต่างมี standard library ที่ค่อนข้างเป็นชุดขั้นต่ำ
- Haskell ไม่มี Map และ HashMap มาให้ในตัว
- OCaml ไม่มี non-empty lists และ Bitraversable
- standard library ของ Haskell คือ
baseส่วนของ OCaml คือ OCaml standard library - คุณภาพเอกสารของ Haskell ดีมากจนบางครั้งแม้แต่นักพัฒนาที่มีประสบการณ์ก็ยังประหลาดใจ
- เอกสารของ Haskell ยังมีข้อดีอย่างความสามารถในการกระโดดไปดู source code ได้ด้วย และผู้เขียนบอกว่าได้ยินมาว่า OCaml ก็กำลังเตรียมฟีเจอร์ลักษณะนี้
-
ตัวอย่างเอกสาร
- ตัวอย่างเอกสาร List ของ Haskell
- ตัวอย่างเอกสาร List ของ OCaml
- แม้จะเป็นฟังก์ชันที่ผลลัพธ์ดูชัดเจนอยู่แล้ว เอกสารที่มีตัวอย่างนำก็ช่วยให้เห็นได้ทันทีว่าจะนำ API ไปใช้อย่างไร
สรุป: ทั้งคู่ใช้ในงานอุตสาหกรรมได้ แต่ตอนนี้เอนเอียงไปทาง OCaml
- ทั้งสองภาษาพัฒนามามากพอจะรองรับความต้องการของงานอุตสาหกรรมจริง
- เมื่อเทียบกับภาษากระแสหลัก ทั้งคู่ยังถือเป็นภาษาขนาดเล็ก
- ถ้าไม่ได้พึ่งพาการมีอยู่ของ SDK เฉพาะทางอย่างมาก ไม่ว่าจะเลือกภาษาไหนก็สามารถพัฒนาแอปถัดไปได้อย่างสนุก
- ตอนนี้ OCaml ถูกประเมินว่าเป็นภาษาที่ช่วยให้โฟกัสกับการสร้างของจริงได้ง่ายกว่า
ยังไม่มีความคิดเห็น