Katharos: Python 的函數式編程與 CSP 風格並行處理

Katharos 是一個針對 Python 3.13+ 的函數式編程與並行處理函式庫,它將隱藏的控制流(例如異常和 None 檢查)替換為顯式、可組合且具備型別安全性的值。透過將代數抽象與訊息傳遞並行模型結合,Katharos 允許開發者將錯誤、可選性與並行通訊視為一等公民值。

代數抽象與型別安全的值

Katharos 實作了核心函數式編程抽象,以消除樣板程式碼並減少與 null 值和異常相關的執行時錯誤。

使用 Maybe 消除 None 檢查

而非散落在各處的 if x is None 檢查,Katharos 使用 Maybe 型別。這允許在值缺失時對邏輯進行乾淨的短路處理。

from katharos.types import Maybe
from katharos.syntax_sugar import do, DoBlock

@do(Maybe)
def lookup_discount(user_id: int) -> DoBlock[Maybe, float]:
    user    = yield find_user(user_id)
    account = yield find_account(user)
    return account.discount  # Returns Just(0.15) or Nothing()

使用 Result 將錯誤處理視為值

Katharos 將錯誤視為值而非異常。Result 型別允許使用管線操作符 (|) 來鏈接錯誤,其中 Failure 會自動短路剩餘的鏈接。

為了減少手動 try/except 的樣板程式碼,@Result.catch 裝飾器會將拋出特定異常的函式轉換為回傳 Result 型別的函式,同時保留原始的 traceback 以供除錯。

from katharos.types import Result

@Result.catch(ValueError)
def parse_int(s: str) -> int:
    return int(s)

# Returns Success(42) or Failure(ValueError(...))
result = parse_int("42")

其他函數式型別

  • ImmutableList: 提供不可變序列,並可以使用 Semigroup 操作符 (@) 進行組合。
  • Algebraic Core: 該函式庫提供了 FunctorApplicativeMonadSemigroupMonoid 的正式實作,以確保不同型別之間的組合一致性。

CSP 風格的並行處理

Katharos 實作了 Go 風格的通訊序列程序 (CSP) 模型用於並行處理,確保並行任務之間的通訊與函數式資料型別一樣具備型別安全性。

訊息傳遞與通道 (Channels)

工作會透過 csp.go 並行啟動,並透過具備型別的 Channel 進行通訊。至關重要的是,從通道接收值會回傳一個 Result。這意味著已關閉或逾時的通道是一個需要進行模式匹配的值,而非需要被捕捉的異常。

from katharos.concurrency.csp import csp

ch = csp.Channel[int](capacity=1)

# Run work concurrently
csp.go(ch.send, 42)

# Receive as a Result value
ch.recv()  # Success(42)

ch.close()
ch.recv()  # Failure(ChannelClosedError(...))

結構化並行處理

當作為上下文管理器使用時,csp.go 會建立一個結構化並行處理作用域。程式會在退出作用域之前加入 (join) 該區塊內啟動的所有工作,以防止類似 goroutine 的任務洩漏。

with csp.go:
    csp.go(worker, 1)
    csp.go(worker, 2)
# Both workers are guaranteed to have finished here

可插拔的後端

Katharos 中的所有並行模型都綁定到 BaseThreadingBackend。雖然標準執行緒是預設值,但這種抽象允許在單一位置將執行時重新定向到不同的後端。未來計畫包含基於此相同後端抽象的 Actor 模型。

實作細節與社群回饋

Do-Notation 機制

Katharos 透過 Python 生成器提供 do-notation,以允許指令式風格的單子 (monadic) 程式碼。然而,社群回饋指出,由於 Python 缺乏 call/cc (call-with-current-continuation),針對某些單子(例如列表單子)的實作可能會涉及重新執行生成器,這可能會限制其使用於較簡單的使用案例或「玩具」範例。

"It's probably worth being up front about what your do syntax actually does. A generator is not as general as "do", Python doesn't have call/cc or anything like that."

需求

Katharos 是為 Python 3.13+ 設計的。

Sources