Katharos: Python 的函数式编程与 CSP 风格并发
Katharos 是一个面向 Python 3.13+ 的函数式编程与并发库,它通过显式、可组合且类型安全的数值,取代了隐藏的控制流(例如异常和 None 检查)。通过将代数抽象与消息传递并发模型相结合,Katharos 允许开发者将错误、可选性以及并发通信视为一等公民数值。
代数抽象与类型安全数值
Katharos 实现了核心的函数式编程抽象,以消除样板代码并减少与空值和异常相关的运行时错误。
使用 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 类型的函数,同时保留原始回溯以供调试。
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: 该库提供了
Functor、Applicative、Monad、Semigroup和Monoid的正式实现,以确保不同类型之间的一致性组合。
CSP 风格并发
Katharos 实现了 Go 风格的通信顺序进程 (CSP) 模型用于并发,确保并发任务之间的通信与函数式数据类型一样具有类型安全性。
消息传递与通道
工作任务通过 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)
n# 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+ 设计的。