Haskell-новичок, сообщающий в.
Вопрос заключается в следующем:
В Haskell мы имеем fst
и snd
, которые возвращают первый и второй элементы 2-кортежа. Почему у нас нет простого доступа к i-му элементу из любого кортежа? Прямо сейчас у меня есть 3-кортеж, я хочу прочитать 1-й элемент, и единственный способ выполнить эту задачу - сделать обход шаблонов. Почему это не может быть сделано проще? Или, может быть, есть простой способ?
Доступ к определенному элементу в кортеже
Ответ 1
Что мешает языку иметь специальную конструкцию, которую вы хотите, это ее дизайн. Дизайнеры просто не ввели это, потому что это усложняло бы определение языка, которое вполне минималистично. fst
и snd
являются библиотечными функциями для общего случая пар; вы можете определить все остальные самостоятельно или, лучше, определить типы записей для своих данных, чтобы ваши члены данных имели соответствующие имена.
(Возможно, GHC имеет расширение для этого, но я не сталкивался с этим, проверяйте документы или спрашивайте в списке рассылки.)
Ответ 2
Ознакомьтесь с библиотекой кортежей в хаке. Он имеет перегруженные функции для различных операций с кортежами (до предопределенного размера).
Ответ 3
N-кортежи не являются структурой данных для индексирования с помощью ключа Int
, вместо этого вы должны посмотреть на структуры с индексированными смещениями, такие как массивы или пальцы.
Теперь можно было бы написать класс типов для семейства типов кортежей, обеспечивающий операцию index
, однако у нас уже есть массивы для что, и там много шаблонов, необходимых для создания кортежей любого типа, легко обеспечить эту операцию. Достигнутая мощность не стоит усилий.
Ответ 4
Почему это нельзя сделать проще? Или, может быть, есть какой-то простой способ?
Это может быть проще, если использовать последнюю альтернативу комплекту линз. Модуль Tuple имеет селекторы для до 9 кортежей элементов, и его легко определить, если необходимо.
> import Control.Lens
> data A = A deriving (Show)
> (1, '2', "3", A) ^. _1
1
> (1, '2', "3", A) ^. _2
'2'
> (1, '2', "3", A) ^. _3
"3"
> (1, '2', "3", A) ^. _4
A
Вы также можете использовать пакет линз для полиморфного обновления элементов, изменения типа при обновлении.
С и без инфиксных операторов:
> (1, '2', "3", A) & _1 .~ "wow"
("wow",'2',"3",A)
> set _1 "wow" (1, '2', "3", A)
("wow",'2',"3",A)
GitHub readme - это хорошее место для начала, чтобы узнать больше о лежащей в основе теории, а также о многочисленных примерах.
Не только кортежи
Подобный синтаксис работает для Traverables
и Foldables
, поэтому дерева, Карты, векторы и т.д. Например, если у меня был список кортежей, я могу получить доступ к третьему элементу кортежа на 1 индекс, составляющие element 1
, чтобы получить доступ к первому индексу элемента с _3
чтобы получить доступ к третьему элементу кортежа.
[(1,2,3),(4,5,6),(7,8,9)] ^? element 1 . _3
Just 6
Ответ 5
Вопрос о подходе к этому использованию с использованием шаблона haskell был ранее описанным здесь.
Пример его использования:
> $(sel 2 3) ('a','b','c') 'b' > $(sel 3 4) ('a','b','c','d') 'c'
Ответ 6
cabal update
cabal install tuple
ghci
λ> import Data.Tuple.Select
λ> sel3 (0, "1", 2) --select the third element
Ответ 7
Никита Волков new "record" library имеет функцию, которая, кажется, делает то, что вы хотите. Искать заголовок "Кортежи - это записи тоже!" на связанной странице.
Похоже, что библиотека все еще находится в разработке, поэтому ее можно будет не так просто установить и использовать прямо сейчас, как это будет в будущем.