Flix – ภาษาโปรแกรมทรงพลังที่มุ่งเน้นเอฟเฟกต์
(flix.dev)- Flix เป็น ภาษาเชิงเอฟเฟกต์ ที่พัฒนาโดย Aarhus University และชุมชนโอเพนซอร์ส โดยผสานการเขียนโปรแกรมเชิงฟังก์ชัน เชิงคำสั่ง และเชิงตรรกะไว้ในภาษาเดียว
- แกนหลักคือ ระบบเอฟเฟกต์ ที่จัดการผลข้างเคียงในระดับชนิดข้อมูล ช่วยเพิ่มความเป็นโมดูลาร์และความสามารถในการให้เหตุผลของโปรแกรมผ่านการติดตามความบริสุทธิ์ เอฟเฟกต์ที่ผู้ใช้กำหนดเอง แฮนด์เลอร์ และการ resume ได้หลายครั้ง
- ผิวหน้าของภาษาครอบคลุมกว้าง ตั้งแต่ชนิดข้อมูลเชิงพีชคณิต, pattern matching, record ที่ขยายได้, trait, higher-kinded type, associated type และ effect, structured concurrency, การทำงานร่วมกับ Java ไปจนถึง Datalog ในตัว
- ไลบรารีมาตรฐานมี ฟังก์ชันมากกว่า 3,100 รายการ และเข้าถึงระบบนิเวศ Java ผ่าน Maven ได้ จึงมุ่งให้ใช้งานได้กว้างกว่าภาษาเพื่อการวิจัยเท่านั้น
- คอมไพเลอร์มุ่งเป้าไปที่ JVM bytecode มีโครงสร้างแบบขนานและ incremental โดยชูตัวเลข เร็วขึ้น 5x–7x บนเครื่อง 24 คอร์ และ throughput 60,159 lines/sec บน Apple M2 Pro/OpenJDK 21
ทิศทางของภาษา Flix
- Flix เป็น ภาษาเชิงเอฟเฟกต์ที่ยึดหลักการ โดยผสานการเขียนโปรแกรมเชิงฟังก์ชัน เชิงคำสั่ง และเชิงตรรกะ
- ผู้พัฒนาหลักคือ Aarhus University และชุมชน ผู้ร่วมพัฒนาโอเพนซอร์ส
- ระบบเอฟเฟกต์เป็นแกนสำคัญของภาษาแบบ static typing ที่ช่วยเรื่อง ความเป็นโมดูลาร์ และการให้เหตุผลเกี่ยวกับโปรแกรม ด้วยการจำลองผลข้างเคียงอย่างชัดเจน
- โปรแกรมเมอร์สามารถสร้างโครงสร้างควบคุมเองได้ผ่านเอฟเฟกต์และแฮนด์เลอร์ที่ผู้ใช้กำหนดเอง
- Flix ชูจุดแข็งด้าน implementation ที่สมบูรณ์ในกลุ่มภาษาเชิงเอฟเฟกต์ ไลบรารีมาตรฐานที่กว้าง เอกสารละเอียด และการรองรับเครื่องมือ
ชนิดข้อมูล ความบริสุทธิ์ และระบบเอฟเฟกต์
- Flix รองรับ ชนิดข้อมูลเชิงพีชคณิต และ pattern matching ซึ่งเป็นองค์ประกอบพื้นฐานของการเขียนโปรแกรมเชิงฟังก์ชัน
- รองรับ tuple และ record ในตัว โดย record ใช้ structural typing และขยายได้
- คอมไพเลอร์ติดตาม ความบริสุทธิ์ ของทุก expression ในโปรแกรมอย่างละเอียด
- หาก expression บริสุทธิ์ จะรับประกันว่าไม่มีผลข้างเคียงและมี referential transparency
- แม้ใน higher-order function ก็ยังติดตามความบริสุทธิ์ด้วย effect polymorphism
- ตัวอย่างเช่น ความบริสุทธิ์ของ
List.mapขึ้นอยู่กับความบริสุทธิ์ของฟังก์ชันfที่รับมาเป็นอาร์กิวเมนต์
- ตัวอย่างเช่น ความบริสุทธิ์ของ
- algebraic effect ทำให้สร้างเอฟเฟกต์และแฮนด์เลอร์ที่ผู้ใช้กำหนดเองได้
- Flix รองรับ multi-shot resumptions เป็นพิเศษ
- effect handler ใช้เพื่อเพิ่มความสามารถในการให้เหตุผลเกี่ยวกับโปรแกรม ความเป็นโมดูลาร์ และความสามารถในการทดสอบ
การเปลี่ยนแปลงแบบอิง region และการสะท้อนความบริสุทธิ์
- Flix รองรับ การเปลี่ยนแปลงภายในแบบอิง region ทำให้สามารถใช้สถานะที่แก้ไขได้และการดำเนินการแบบทำลายค่าเดิมภายในได้ แต่ภายนอกยังดูเป็นฟังก์ชันบริสุทธิ์
- เหมาะกับฟังก์ชันที่เขียนด้วยข้อมูลที่แก้ไขได้แล้วเป็นธรรมชาติกว่า หรือกรณีที่โครงสร้างข้อมูลแบบแก้ไขได้มีประสิทธิภาพกว่าสำหรับอัลกอริทึมอย่างการเรียงลำดับ
- การสะท้อนความบริสุทธิ์ เป็นโครงสร้าง metaprogramming ที่ higher-order function ตรวจสอบความบริสุทธิ์ของอาร์กิวเมนต์ฟังก์ชัน และเปลี่ยนพฤติกรรมตามข้อมูลนั้น
DelayList.mapเปลี่ยนพฤติกรรมระหว่างการประเมินผลทันทีและการประเมินผลแบบ lazy ตามความบริสุทธิ์ของฟังก์ชันอาร์กิวเมนต์- แม้ภายในไลบรารีจะเลือกใช้การประเมินผลแบบ lazy หรือแบบขนาน ความหมายในมุมมองของ client ก็อาจไม่เปลี่ยน
ความขนาน ความพร้อมกัน และ abstraction
- Flix ทำให้ประเมินผลโค้ดบริสุทธิ์แบบขนานได้ง่าย และสามารถเขียน implementation แบบขนานของ
List.mapด้วยโครงสร้างpar - โครงสร้าง
parใช้ VirtualThread แบบ lightweight ภายใน - รองรับ structured concurrency โดย thread ที่สร้างภายใน region หนึ่งจะไม่สามารถมีชีวิตอยู่นอก lifecycle ของ region นั้นได้
- ในตัวอย่าง มีการสร้าง thread สองตัวใน region ใหม่ชื่อ
rc - control flow จะไม่ออกจาก region จนกว่า thread ทั้งสองจะสิ้นสุด
- ในตัวอย่าง มีการสร้าง thread สองตัวใน region ใหม่ชื่อ
- การทำ abstraction ของชนิดข้อมูลที่รองรับ operation ร่วมกันใช้ trait
- trait
Eqแสดงแนวคิดของความเท่ากัน และใช้ทั่วไลบรารีมาตรฐาน
- trait
- higher-kinded type ทำให้ทำ abstraction เหนือ type constructor ได้
- ทั้ง
OptionและListimplementFoldable - ไลบรารีมาตรฐานมี trait ทั่วไปอย่าง
Monoid,Functor,Foldable
- ทั้ง
Associated type/effect และ for-yield
- Flix รองรับ associated type ที่ทำให้ชนิดข้อมูลใน signature ของ instance ขึ้นกับชนิดของ instance ได้
- ตัวอย่าง trait
Collทำให้แต่ละ collection instance กำหนดชนิดของ element ได้ผ่าน associated typeElm
- ตัวอย่าง trait
- Associated effect ทำให้เอฟเฟกต์ของสมาชิก trait ขึ้นกับชนิดของ instance
- ช่วยให้ abstract operation บริสุทธิ์กับ operation ที่มีเอฟเฟกต์ รวมถึงโครงสร้างข้อมูลแบบแก้ไขได้กับแบบ immutable ได้ง่ายขึ้น
- เมื่อเพิ่ม associated effect
Aefให้ traitCollก็สามารถเพิ่ม instance ของ collection แบบแก้ไขได้
forM-yield เป็นโครงสร้างแบบ monadic ที่คล้ายfor-comprehension ของ Scala และสัญกรณ์doของ Haskell- เป็น syntax sugar สำหรับใช้
pointและflatMapที่ traitMonadให้มา
- เป็น syntax sugar สำหรับใช้
forAเป็น expression แบบ applicative ที่อิง traitApplicative- เป็นโครงสร้างที่ช่วยให้เขียนโค้ดจัดการข้อผิดพลาดโดยใช้ชนิดข้อมูล
Validation[e, t]ได้ง่ายขึ้น
- เป็นโครงสร้างที่ช่วยให้เขียนโค้ดจัดการข้อผิดพลาดโดยใช้ชนิดข้อมูล
การทำงานร่วมกับ Java และ Datalog
- Flix รองรับ การทำงานร่วมกับ Java เพื่อใช้ Java Standard Library และโค้ดจากระบบนิเวศ Java ซ้ำได้
- รวมถึงการเข้าถึงระบบนิเวศผ่าน Maven
- รองรับการสร้าง object, การเรียก method, exception, และการขยาย class/interface
- การรองรับ Datalog ในตัวเป็นหนึ่งในความสามารถเฉพาะของ Flix
- Datalog สามารถแสดงปัญหา fixed point หลายแบบอย่างกระชับ รวมถึงปัญหา reachability ของกราฟ
- Datalog constraint เป็น first-class value
- ส่งให้ฟังก์ชันหรือคืนค่าจากฟังก์ชันได้
- เก็บไว้ในโครงสร้างข้อมูลได้
- ประกอบกับ Datalog constraint อื่นและแก้ได้
- ทำให้แสดงกลุ่มของโปรแกรม Datalog ได้
- Flix ยังรองรับ Datalog constraint ที่เสริมด้วย lattice semantics
- มีตัวอย่างการคำนวณวันส่งมอบของชิ้นส่วนและชิ้นส่วนย่อย
- รถยนต์ขึ้นกับแชสซีและเครื่องยนต์ และประกอบรถได้หลังรอให้แต่ละชิ้นส่วนประกอบเสร็จ
- ชิ้นส่วนย่อยก็อาจขึ้นกับชิ้นส่วนย่อยอื่น ทำให้ปัญหาเป็นแบบ recursive
- Datalog constraint ที่รวม lattice semantics เป็นหนึ่งในฟีเจอร์ขั้นสูงของ Flix และต้องมีพื้นฐานด้าน lattice theory กับ fixed point
ไลบรารีมาตรฐานและรายการฟีเจอร์
- Flix มีไลบรารีมาตรฐานที่ให้ ฟังก์ชันมากกว่า 3,100 รายการ
- โมดูล
Listให้ฟังก์ชันมากกว่า 100 รายการ - trait
Foldableให้ฟังก์ชันมากกว่า 47 รายการ - สามารถสำรวจไลบรารีทั้งหมดได้ที่ api.flix.dev
- โมดูล
- รายการฟีเจอร์ประกอบด้วย
- ชนิดข้อมูลเชิงพีชคณิต, pattern matching, first-class function
- record ที่ขยายได้, parametric polymorphism
- trait, higher-kinded type, associated type และ effect
- effect polymorphism และ sub-effect, การสะท้อนความบริสุทธิ์
- concurrency สไตล์ CSP, channel แบบมี buffer และไม่มี buffer
- first-class Datalog constraint, การทำงานร่วมกับ Java
- primitive type แบบ unboxed, syntax แบบใช้ keyword
forM,forA, expression hole- การคอมไพล์เป็น JVM bytecode, การกำจัด tail call อย่างสมบูรณ์
- โครงสร้างคอมไพเลอร์แบบยืดหยุ่นและขนาน, ข้อผิดพลาดที่มนุษย์อ่านเข้าใจง่าย
โครงสร้างและประสิทธิภาพของคอมไพเลอร์
- คอมไพเลอร์ Flix มีโครงสร้างแบบ ยืดหยุ่น incremental และขนาน
- ทุกขั้นตอนของคอมไพเลอร์ทำงานแบบขนาน และสามารถใช้ประโยชน์จากความเร็วที่เพิ่มขึ้นของแต่ละขั้นตอนบนเครื่อง 24 คอร์ได้
- บนเครื่อง multicore สามารถทำความเร็วเพิ่มขึ้นได้ 5x–7x
- เมื่อคอมไพล์โค้ดที่เคยคอมไพล์แล้วอีกครั้งใน instance คอมไพเลอร์เดียวกัน จะได้ความเร็วเพิ่มขึ้นอย่างมากจาก incremental compilation
- ตัวเลขประสิทธิภาพบน CPU Apple M2 Pro 10 คอร์ และ OpenJDK 21 มีดังนี้
- throughput รวมของคอมไพเลอร์: 60,159 lines/sec
- throughput เฉพาะ frontend: 140,382 lines/sec
- คำสั่งสำหรับทำซ้ำคือ
java -jar flix.jar Xperf --n 21และjava -jar flix.jar Xperf --frontend --n 21
- ประสิทธิภาพนี้ทำได้พร้อมกับรองรับฟีเจอร์ของภาษาที่มีต้นทุนสูง เช่น type/effect inference, monomorphization และ whole-program optimization
- ประสิทธิภาพคอมไพเลอร์ขึ้นอยู่กับประสิทธิภาพ CPU และ memory bandwidth เป็นหลัก
การรองรับ Visual Studio Code และการผสานเครื่องมือ
- คอมไพเลอร์ Flix ผสานกับ Visual Studio Code เพื่อให้สภาพแวดล้อมการพัฒนา
- ส่วนขยาย VSCode ใช้คอมไพเลอร์ Flix จริง จึงมี ความสอดคล้องแบบ 1:1 ระหว่างส่วนขยายกับคอมไพเลอร์
- หาก VSCode ไม่รายงานข้อผิดพลาด แปลว่าไม่มีข้อผิดพลาด
- เมื่อไม่มีข้อผิดพลาด VSCode จะไม่รายงานข้อผิดพลาดปลอม
- ส่วนขยาย VSCode รองรับฟีเจอร์ต่อไปนี้
- syntax highlighting ตามความหมาย
- diagnostics ข้อผิดพลาดจากคอมไพเลอร์แบบ inline
- autocomplete ระหว่างพิมพ์, autocomplete ตามบริบท, autocomplete trait instance, การเติม hole ตามชนิดข้อมูล
- snippet และ inlay hint
- hover ที่แสดงชนิดข้อมูลและเอฟเฟกต์ของ expression
- ไปยังนิยามของฟังก์ชัน ตัวแปรท้องถิ่น และ enum
- ค้นหา reference ของฟังก์ชัน ตัวแปรท้องถิ่น และ enum รวมถึงค้นหา implementation ของ trait
- รายการ symbol ของเอกสารและ workspace
- เปลี่ยนชื่อตัวแปรท้องถิ่นและฟังก์ชัน
- รัน main และรันทดสอบจาก editor
- Flix ฝังเครื่องมือจำนวนมากไว้ในคอมไพเลอร์โดยตรง
- OCaml ใช้
ocaml-lspเป็น LSP,utopเป็น REPL,duneเป็น build tool และopamเป็น package manager - Haskell ใช้
HLSเป็น LSP,ghciเป็น REPL,cabalและstackเป็น build tool และ package manager และใช้Hackageเป็น package repository - Flix ให้คอมไพเลอร์, LSP, REPL, build tool และ package manager ทั้งหมดผ่าน
flixและใช้ GitHub เป็น package repository
- OCaml ใช้
สถานะการพัฒนา เป้าหมาย JVM และขนาดโปรเจกต์
- Flix พัฒนาและดูแลโดยนักวิจัยด้านภาษาโปรแกรมจาก Aarhus University ประเทศเดนมาร์ก
- สถาบันที่ร่วมมือกันคือ University of Waterloo ในแคนาดา, University of Tubingen ในเยอรมนี และ Copenhagen University ในเดนมาร์ก
- การมีส่วนร่วมพัฒนาจากชุมชนโอเพนซอร์สทั่วโลกกำลังเพิ่มขึ้น และเปิดรับผู้ร่วมพัฒนา
- สถิติโปรเจกต์มีดังนี้
- Pull Request ที่ merge แล้ว: มากกว่า 4,900 รายการ
- issue ที่แก้แล้ว: มากกว่า 3,100 รายการ
- ผู้ร่วมพัฒนา: มากกว่า 70 คน
- codebase ของคอมไพเลอร์: มากกว่า 272,000 บรรทัด
- Flix มุ่งเป้าไปที่ JVM
- JVM มี implementation ทั้งโอเพนซอร์สและเชิงพาณิชย์ที่ผ่านการพิสูจน์แล้ว เช่น OpenJDK, J9, Azul, Graal
- ใช้งานได้บน Mac, Linux, Windows
- JVM สมัยใหม่มี garbage collector รุ่นใหม่หลายแบบ
- รองรับ concurrency และ parallelism ได้ดี รวมถึง lightweight thread ของ Java 21
- มีการรองรับเครื่องมือ เช่น debugger และ profiler
- การผสานกับ Maven ทำให้เข้าถึงระบบนิเวศแพ็กเกจอันหลากหลายของแพลตฟอร์ม Java ได้
- เงินทุนรวมอยู่ที่ 1.1 ล้านยูโร ซึ่งช่วยรับประกันความต่อเนื่องและความเป็นอิสระของโปรเจกต์
ยังไม่มีความคิดเห็น