Lobsters | 原文链接 | 2026-09-04 收录

没有依赖类型也能做依赖 if 表达式:Haskell 的类型级小把戏

来源: haskellforall.com — 2026-09-02

概述

Gabriella Gonzalez 展示一个 folklore 技巧:在无需依赖类型的语言里实现'看似依赖类型'的代码——if bool then 5 else \「hi!\」 会随 bool 返回不同种类(Int 或 String)。关键是把布尔的 Church 编码泛化:与其用 forall a. a->a->a 让两个分支同型,不如删掉所有类型签名与 RankNTypes,只保留 RebindableSyntax,让编译器推断出更一般的类型 Bool thenBranch elseBranch result = thenBranch -> elseBranch -> result。于是 true 的类型是 thenBranch->elseBranch->thenBranch、false 是 thenBranch->elseBranch->elseBranch,ifThenElse 的结果类型随传入的布尔而变——类型信息顺着分支流动,编译器据此为 example 推断出 Bool Int String result -> result。只用约 20 行普通函数式代码、纯类型系统特性即可表达类似 example :: (bool::Bool) -> if bool then Int else String 的效果。混用 true 与 false 时类型会优雅退化回未精化布尔(两分支须同型)。再开 DataKinds 与 TypeFamilies 还能实现编译期断言:assert false 会直接报'Assertion failed'类型错误。作者也把该技巧与 Church 编码、访客模式、fold 联系起来。

核心要点

金句

The reason this all works is because our new Bool type tracks information flow at the type-level.(这一切之所以成立,是因为我们的新 Bool 类型在类型层面追踪了信息流。)
返回 Lobsters 首页