Andrew Koenig のAn anecdote about ML type inferenceで、著者はマージ ソートの実装を ML の学習演習として使用し、「正しくない」型推論を発見して喜んでいます。
驚いたことに、コンパイラは次のタイプを報告しました。
'a list -> int list
つまり、このソート関数は、あらゆるタイプのリストを受け入れ、整数のリストを返します。
それは不可能です。出力は入力の順列でなければなりません。どのように異なるタイプを持つことができますか? 読者はきっと、私の最初の衝動に親しみを覚えるでしょう。コンパイラのバグを発見したのではないかと思ったのです!
もう少し考えてみたところ、関数が引数を無視する別の方法があることに気付きました。確かに、私が試してみたところ、まさにそれが起こったのです:
sort(nil)
return でしたnil
が、空でないリストを並べ替えると、無限再帰ループに入ります。
Haskellに翻訳すると
split [] = ([], [])
split [x] = ([x], [])
split (x:y:xs) = (x:s1, y:s2)
where (s1,s2) = split xs
merge xs [] = xs
merge [] ys = ys
merge xx@(x:xs) yy@(y:ys)
| x < y = x : merge xs yy
| otherwise = y : merge xx ys
mergesort [] = []
mergesort xs = merge (mergesort p) (mergesort q)
where (p,q) = split xs
GHC は同様の型を推論します:
*Main> :t mergesort
mergesort :: (Ord a) => [t] -> [a]
Damas-Hindley-Milner アルゴリズムはどのようにこの型を推測しますか?