Подтвердить что ты не робот

Haskell: Алгебраические данные против Tuple

data Ray = Ray Vector Vector

или

type Ray = (Vector, Vector)

Что предпочтительнее в идиоматическом haskell? Почему я должен использовать один над другим?
Меня не волнует производительность.

Кажется, что это мало чем отличается от функций, например:

trace :: Ray -> …

trace (Ray x d) = …
-- OR
trace (x, d) = …
4b9b3361

Ответ 1

Версия data предпочтительнее, поскольку она более четко указывает на намерение программиста - создавая новый тип, вы указываете на все, что это не просто кортеж, а значимая семантическая сущность, a Ray.

Это позволяет далее опираться на систему типов с пользовательскими экземплярами для Ray, а оптимизация невозможна в кортежах.

Ответ 2

Вы также можете рассмотреть третий вариант, который представляет собой комбинацию из двух: newtype

newtype Ray = Ray (Vector, Vector)

Алгебраические типы данных, на мой взгляд, используются в ситуациях, когда у вас есть несколько альтернатив, или в тех случаях, когда вам нужен тип, который будет рекурсивным, содержащий себя. Но это может быть излишним для чего-то подобного.

Дон Стюарт отметил, что создание синонима типа для кортежа - это то же самое, что и использование этого типа кортежа; синонимы типов не имеют собственной идентичности. Таким образом, средство проверки типов не сможет различать ваш тип и кортеж, и поэтому он не может проверить, что вы используете тот тип, который вам нужен. Кроме того, он имел бы те же экземпляры, что и кортеж.

A newtype позволяет использовать тот же базовый тип, что и кортеж; но это отдельный тип для проверки типов, с отдельными экземплярами.

Ответ 3

Четвертая альтернатива, которую я нашел довольно удобной, - это записи:

data Ray = Ray { from, to :: Vector } 

У них есть в основном все функции "нормальных" ADT, но с некоторым дополнительным синтаксическим сахаром. Особенно они облегчают получение частично модифицированных копий значения. Правда, в некоторых ситуациях записи слишком ограничены, но тогда вы можете продолжить "улучшенные версии", например fclabels.