【发布时间】:2010-12-22 05:57:13
【问题描述】:
在 Andrew Koenig 的 An anecdote about ML type inference 中,作者使用 merge sort 的实现作为 ML 的学习练习,很高兴发现“不正确”的类型推断。
令我惊讶的是,编译器报告了一种
'a list -> int list换句话说,这个排序函数接受任何类型的列表并返回一个整数列表。
那是不可能的。输出必须是输入的排列;它怎么可能有不同的类型?读者肯定会发现我的第一个冲动很熟悉:我想知道我是否在编译器中发现了一个错误!
再想一想之后,我意识到还有另一种方法可以让函数忽略它的参数:也许它有时根本不返回。事实上,当我尝试它时,确实发生了这样的事情:
sort(nil)确实返回了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 algorithm 是如何推断这种类型的?
【问题讨论】:
标签: haskell type-inference type-systems ml hindley-milner