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

ข้อความจากคอมไพเลอร์: 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 ถูกประเมินว่าเป็นภาษาที่ช่วยให้โฟกัสกับการสร้างของจริงได้ง่ายกว่า

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น