在第 14 章之后,第 15 章之前,《The Little Typer》用了一整页描述 Tuner’s Teaser,它的内容就是:定义一个函数,接受任意一个可接受一定数量 Eiher
作为参数的函数 f
,判断 f
是否总会返回 left
。假设要定义的函数叫 taut
,那它必须能接受 (→ Either Either)
,(→ Either Either Either)
,(→ Either Either Either Either)
乃至任意层多的类型的参数。
以上描述里忽略了 Either
的两个类型参数,Friedman 的代码用的是 (Either Trivial Trivial)
类型,并定义其为 Two
类型。在这篇文章里将采用更熟悉的名称:Bool
,这样 Tuner’s Teaser 就是定义一个函数,判断另一个可能接受任意数量 Bool
的函数是否总是返回 true
。
1 | (claim Bool U) |
Tuner’s Teaser 的核心是怎么描述“可能接受任意数量 Bool
的函数”的类型。要描述这种类型,要注意到 Pie 的函数是柯里化的, (→ Bool Bool Bool)
其实是 (→ Bool (→ Bool Bool))
的语法糖,容易看出这种形式与 Nat
同构,于是可以通过解构 Nat
来给出归纳描述:
1 | (claim Bool-Fun (→ Nat U)) |
这样 (Bool-Fun zero)
就是 Bool
,传入非 zero
的 n
时 (Bool-Fun n)
就是接受 n
个 Bool
参数的函数类型。
再定义一个 and
函数,功能和一般的 and
一样:
1 | (claim and (→ Bool Bool Bool)) |
接下来就可以定义 taut
了:
1 | (claim step-taut |
关键部分是 step-taut
,它把一个判断 (Bool-Fun n)
的函数升级为判断 (Bool-Fun (add1 n))
的函数,这样在 taut
中即可完成对“所有”n
的定义,升级方法是考虑要检验的函数 f
第一个参数分别为 true
和 false
的情况,而 (f b)
就退化为 (Bool-Fun n)
,可以用上一级函数检测了,检测完后用 and
测试是否皆为 true
即可。
使用示例:(taut 2 and)
,返回 (the (Either Trivial Trivial) (right sole))
,也就是 false
。