Bridging the Gap: Introducing hsrs, a Type-Safe Haskell Bindings Generator for Rust

整合 Rust 與 Haskell——這兩種現代程式設計中最強大的型別系統——是一個強大的組合。然而,在兩者之間建立橋樑在歷史上一直充滿摩擦。直到現在,大多數的綁定生成器都缺乏開發者對這兩種語言所期望的豐富且具備型別安全性的介面。

介紹 hsrs,一個為 Rust 設計的型別安全 Haskell 綁定生成器。hsrs 的設計理念與 pyo3napi-rs 等工具相似,旨在提供一種更符合人體工學且具備型別安全性的方式,將 Rust 程式碼整合到 Haskell 應用程式中。

The Need for Type-Safe Bindings

許多開發者一直苦於缺乏能夠自動生成豐富綁定的工具。雖然存在像 hs-bindgen 這樣的工具,但 hsrs 的獨特之處在於它能為 ResultMaybe 等複雜型別提供型別安全的綁定。這確保了當從 Haskell 調用程式碼時,能保留 Rust 型別系統所提供的相同安全保證,從而防止常見的 FFI (Foreign Function Interface) 介面錯誤。

Key Features and Architecture

Hsrs 利用 Rust 的程序化宏 (procedural macros) 讓開發者可以標記要匯出的函數與資料型別。藉此,它能生成必要的膠合程式碼 (glue code),讓 Haskell 能與 Rust 的 struct 與函數無縫互動。

Handling Data Types

hsrs 最顯著的優勢之一是它能夠將 Rust 的 struct 處理為 ForeignPtr(用於基於引用的互動)或作為具有完整封裝 (marshalling) 功能的原生 Haskell records。這種靈活性讓開發者可以在將資料保留在 Rust 端與將其保留在 Haskell 端之間,選擇效能權衡。

Function Mapping

目前,該工具會將標記為 #[hsrs::function] 的 Rust 函數轉換為回傳 IO action 的 Haskell 函數。這是一個必要的設計選擇,因為 Rust 函數可以執行任意的副作用,而 Haskell 的純度則透過將這些調用封裝在 IO monad 中來維持。

Community Insights and Future Directions

社群對 the_flux 的反應顯示,Haskell 的 GC (Garbage Collector) 與 Rust 的所有權模型 (ownership model) 之間的 GC 互動是主要的摩擦點。正如使用者 @_flux 所言:

It would be so nice if these "well typed languages" would be able to interact better with each other. Alas, the GC will probably cause some friction... Maybe the GC would be less of a problem if we didn't want to have the best possible performance as well.

儘管存在這些挑戰,此工具開啟了透過利用 Rust 編寫的函式庫來擴展 Haskell 生態系統的可能性,而 Rust 目前正經歷著生態系統的巨大增長。

Potential Enhancements

根據社群的回饋,已確定了幾個未來改進的領域:

  • Pure Function Marking: 能夠將某些 Rust 函數標記為純函數(不安全地)以避免將其封裝在 unsafePerformIO 中,並獲得純粹的 Haskell 函數。

  • Trait Translation: 由於兩種語言都共享 Hindley-Milner (HM) 型別系統,因此有潛力將 Rust traits 轉換為 Haskell type classes,從而提供更深層次的複型 (polymorphic) 整合。

  • External Library Integration: 改進為來自外部 Rust 函式庫的型別生成 #[hsrs::data_type] 綁定的能力,而無需要求自定義的包裝型別。

透過提供一個更符合人體工學的橋樑,hsrs 讓開發者能夠在利用 Rust 的效能與安全性之餘,同時維持 Haskell 的高階抽象。

Sources