こわくない Idris (5)
表明から証明へ (2)
型と命題
カリー゠ハワード同型対応により、プログラムと証明が対応すると述べた。実際にはどのように対応しているのだろうか? 実は、恒真である命題は、空でない(その型である値を持つ)型に対応しているのだ。
型と命題の対応関係を見てみよう。
型 | 命題 |
---|---|
(x : A) -> P x |
|
(x : A ** P x) |
|
Not P |
|
(P, Q) |
|
Either P Q |
|
P -> Q |
ここで、NotはBuiltins.idrで次のように定義されている。
Not : Type -> Type Not a = a -> _|_
_|_ という奇妙な型は、HaskellのData.Void型と同じで、その型である値を持たない型だ。_|_を証明として読むと、矛盾があるという意味に読むことができる。
=
重要なデータ型に(=)
がある。これはビルトインのデータ型だが、チュートリアルによれば概念的には次のように表せるものだ。
data (=) : a -> b -> Type where refl : x = x
x = y
という型は、x と y が同じものである場合にだけ、refl
という値を持つ。値を持つ型は恒真であると読み替えることができたから、すなわち、x = y
という型が空でないことが、xとyが等しいことの証明になっている。
例えば、Idrisにおける、Listに対するhead函数は次のような型を持っている。
head : (l : List a) -> (isCons l = True) -> a
これは、第1引数にリストを取る他に、第2引数にそのリストがコンスセルである(Nilでない)「証明」を要求していることになる。もし isCons l = True が証明できなければ、そのような型を持つ値を渡すことができず、型が合わないから型検査時にエラーになる。
Idris> head [1, 2, 3] refl 1 : Integer Idris> head [] refl Can't unify x = x with isCons [] = True Specifically: Can't unify False with True
so
もうひとつ、so
というデータ型も紹介する。
data so : Bool -> Type where oh : so True
so True
という型はoh
という値をもつ一方で、so False
という型は空だ。実質的にso P
という型はP = True
のことだと考えてよい。