Почему нет никаких "общих" функций доступа для кортежей в Haskell?

Я знаю, что есть fst и snd, но почему нет "общего" определения для таких функций доступа с использованием классов типов? Я бы предложил что-то вроде

class Get1 p a | p -> a where
  get1 :: p -> a 

instance Get1 (a,b) a where
  get1 (x,_) = x 

instance Get1 (a,b,c) a where
  get1 (x,_,_) = x 

class Get2 p a | p -> a where
  get2 :: p -> a 

instance Get2 (a,b) b where
  get2 (_,x) = x 

instance Get2 (a,b,c) b where
  get2 (_,x,_) = x 

Конечно, для этого вам нужны некоторые языковые расширения, но разве это не намного удобнее? Особенно вы можете добавлять экземпляры для своих собственных типов.

Ответ 1

Следует отметить, что fst и snd позволяют просматривать только 2-кортеж. Обобщение их на другие предметы и операции быстро становится болезненным. Если вы хотите, например, отобразить первый элемент кортежа, вы должны ввести другой комбинатор (который для записи существует для 2-х кортежей как Control.Arrow.first). Это быстро приводит к взрыву количества комбинаторов для кортежей с высокой степенью достоверности.

При этом lens предоставляет некоторые полезные инструменты для работы с кортежами. Control.Lens.Tuple содержит несколько объективов с индексом _1, _2 и т.д., которые разрешают доступ к первым, вторым и т.д. элементам кортежей до arity 9.

Например,

>>> import Control.Lens
>>> let t = (1,2,3,5,6,7,2)
>>> t ^._1
1
>>> t & _1 .~ 'a'
('a',2,3,5,6,7,2)
>>> t & _1 +~ 41
(42,2,3,5,6,7,2)
>>> over _1 (+1) t
(2,2,3,5,6,7,2)

Вы также можете быть заинтересованы в экземплярах tuple в Control.Lens.At. Кроме того, tuple-lenses package предоставляет некоторые более общие объективы для одновременного изучения нескольких элементов кортежа.

Ответ 2

Такие классы классов дают только удобство кодирования (синтаксиса), я не вижу, как создавать на них обобщенные инструменты типа tuple. Если вы ищете обобщение кортежа, проверьте обсуждение гетерогенных векторов на Reddit.

Также обратите внимание, что для обычных структур предпочтительнее определять свои собственные ADT и предоставлять геттеры с разумными именами, а затем использовать кортежи высокой степени.

Изменить: однако, как указано в примечании is7s, существует ряд пакетов хакажа, которые предоставляют функции индексирования для кортежей произвольной длины.