В Andrew Koenig & ss Анекдот о выводах типа ML автор использует реализацию 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 [email protected](x:xs) [email protected](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 – алгоритм Милнера вывести этот тип?