Рассмотрим следующие два определения двоичного дерева:
data Tree a = Empty | Node a (Tree a) (Tree a)
data Tree a = Empty | Node (Tree a) a (Tree a)
Я знаю, что это несколько тривиальный вопрос, но мне интересно, есть ли какая-либо конкретная причина предпочитать один порядок параметров другому.
Когда мы переходим от императивных языков к функциональным, мы узнаем, что порядок параметров внезапно становится очень важным из-за каррирования. Аналогичным образом, когда мы переходим от функционального языка к языку с зависимой типизацией, мы узнаем, что порядок, в котором мы вводим определения в файле, внезапно становится очень важным из-за проверки целостности/завершения.
В Haskell часто возникает стилистический выбор, будут ли функции верхнего уровня/точки входа располагаться вверху или внизу файла, но, например, Агда, есть только один выбор. Вспомогательные функции должны быть определены первыми, а элементы верхнего уровня располагаются внизу. Так что на самом деле есть естественный выбор.
Есть ли здесь естественный выбор по какой-либо веской причине?
Да, именно об этом я и думал. Я подумал, что, возможно, у кого-то может быть потрясающий пример стандартной функции/алгоритма, который вы хотели бы реализовать, который был бы гораздо более естественным, например. Node val
, или наоборот
Если вы выведете Ord
, то порядок сортировки будет другим.
Я бы сказал, что это не основано на мнениях, поскольку здесь спрашивается какая-либо объективная причина, почему это будет предпочтительнее в любом контексте, а не то, какой из них на самом деле предпочтительнее.
Это не имеет особого значения.
Нет никаких причин, связанных с набором текста, для предпочтения.
Я не вижу никаких причин, связанных с производительностью.
Причиной может быть частичное применение Node
, но я считаю, что это случается очень редко для Node
.
Еще одна потенциальная причина предпочесть любой из них: автоматически полученные экземпляры. Особенно deriving Ord
, который будет по-другому расставлять деревья. (Тем не менее, по моему опыту, сравнение деревьев не очень распространено.) Кроме того, deriving (Foldable, Traversable)
обеспечит различные сгибы и траверсы.
При прочих равных условиях мое личное предпочтение таково:
data Tree a = Empty | Node (Tree a) a (Tree a)
потому что дерево может быть двоичным деревом поиска (BST), и в таком случае я считаю, что наличие Node left x right
помогает запомнить, что значения в left
меньше, чем x
, что меньше значений в right
.
Если не считать предпочтений в том, как вы можете частично использовать
Node
, я не думаю, что это имеет значение.Node newRoot
против\l r -> Node l newRoot r
, например.