Это тесно связано с вашим другим вопросом о Haskell и quicksort. Я думаю, вам, вероятно, нужно прочитать хотя бы введение книги о Haskell. Это звучит так, как будто вы еще не поняли ключевой момент, связанный с тем, что он запрещает вам изменять значения существующих переменных.
Swap (как понимается и используется в C++), по своей природе, все об изменении существующих значений. Таким образом, мы можем использовать имя для обозначения контейнера и заменять этот контейнер совершенно другим содержимым и специализируемся на том, чтобы эта операция была быстрой (и исключающей) для конкретных контейнеров, что позволило нам реализовать подход изменения и публикации (что важно для написания кода, безопасного для исключения кода, или попытки написать код без блокировки).
Вы можете написать общий своп в Haskell, но он, вероятно, возьмет пару значений и вернет новую пару, содержащую те же значения, с их позициями, или что-то в этом роде. На самом деле это не то же самое, и не имеет одинакового использования. Было бы нецелесообразно пытаться и специализировать его для карты, копаясь внутри этой карты и меняя ее отдельные переменные-члены, потому что вам просто не разрешают делать подобные вещи в Haskell (вы можете заниматься специализацией, но не изменение переменных).
Предположим, мы хотим, чтобы "измерить" список в Haskell:
measure :: [a] -> Integer
Это объявление типа. Это означает, что функция measure
принимает список всего (a
- это параметр общего типа, поскольку он начинается с строчной буквы) и возвращает целое число. Таким образом, это работает для списка любого типа элемента - это то, что будет называться шаблоном функции в C++ или полиморфной функцией в Haskell (не такой, как полиморфный класс в C++).
Теперь мы можем определить, что предоставление специализаций для каждого интересного случая:
measure [] = 0
т.е. измерить пустой список и вы получите ноль.
Вот очень общее определение, которое охватывает все другие случаи:
measure (h:r) = 1 + measure r
Бит в скобках на LHS является образцом. Это означает: взять список, отколоть голову и называть его h, вызвать оставшуюся часть r. Эти имена являются параметрами, которые мы можем использовать. Это будет соответствовать любому списку с хотя бы одним элементом.
Если вы пробовали метапрограммирование шаблона на C++, это все будет для вас старой шляпой, потому что она включает в себя точно такой же стиль - рекурсия, чтобы делать циклы, специализация, чтобы завершить рекурсию. За исключением того, что в Haskell он работает во время выполнения (специализация функции для определенных значений или шаблонов значений).
Это шутка, не так ли? Это похоже на то, как вы можете точно контролировать все в сборке: P – ShreevatsaR
Ничего общего с сборкой. Просто поддерживайте один и тот же интерфейс с семейством алгоритмов. – obecalp
Помимо странного вопроса о родовом программировании и частичной специализации (поиск currying), вопрос о «замене переменных» также странный: в Haskell нет такой вещи, как «замена содержимого двух ящиков», поскольку переменные в Haskell * не * ящики с данными в них. – ShreevatsaR